Define sub-types or not?

Consider the following contrived example:

Suppose I wanted to implement my own custom Weight types and let’s say that some of them can be converted to standard units (pounds, kilograms, etc.) while others (for some strange reason) are not convertible to other units at all. What’s the recommended way to define the types in this scenario? I could define a Weight type that has an isconvertible field and then in my convert_to(w::Weight, units) function just check to see if it’s convertible, throwing an Error if not.

struct Weight
    value::Real
    isconvertible::Bool
end

function convert_to(w::Weight, units)
    w.isconvertible == false && throw(ArgumentError("Sorry, this weight is not convertible to other units"))
end

Or, I could just define Weight as an abstract type and then have ConvertibleWeight and NonConvertibleWeight as subtypes. Is there a preferred/recommended way to deal with this kind of situation?

1 Like

Either approach is OK. I prefer the " Or, I could just define Weight as an abstract type and then have ConvertibleWeight and NonConvertibleWeight as subtypes." approach as it does not carry an extra field in the struct (though it duplicates structs – but that’s ok here, as the functionality is well coordinated). A third approach to make convertibility a trait (perhaps using SimpleTraits.jl as you are new to this).

1 Like

It depends on two things, mostly:

  1. do you want to dispatch on a weight being convertible?

  2. can you fit into a type hierarchy with single inheritance?

For (1), you need either subtypes or traits. If (2) does not hold, traits are your only option.

I would go with subtypes in the first iteration but expose that via a function like is_convertible, so that refactoring is easy.

1 Like