# Understanding supertypes

**URL:** <https://discourse.julialang.org/t/understanding-supertypes/24971>\
**Category:** New to Julia\
**Created:** [June 5, 2019, 3:57pm UTC](https://discourse.julialang.org/t/understanding-supertypes/24971 "2019-06-05T15:57:17Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Paul\_McVay](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_mcvay/32/4307_2.png) [@Paul\_McVay](https://discourse.julialang.org/u/Paul_McVay)\
**Post date:** [June 5, 2019, 3:57pm UTC](https://discourse.julialang.org/t/understanding-supertypes/24971/1 "2019-06-05T15:57:17Z")

</div>

I’m a little confused about how supertypes work and the inheritance of methods. Say for example, I define my own type with integer as the supertype. How can I use the integer methods with my type?

```julia
primitive type MyInt <: Integer 64 end

function MyInt(x::Int)::MyInt
    return reinterpret(MyInt, x)
end

MyInt(8) + MyInt(8) 

```

```julia
ERROR: promotion of types MyInt and MyInt failed to change any arguments
Stacktrace:
 [1] error(::String, ::String, ::String) at ./error.jl:42
 [2] sametype_error(::Tuple{MyInt,MyInt}) at ./promotion.jl:308
 [3] not_sametype(::Tuple{MyInt,MyInt}, ::Tuple{MyInt,MyInt}) at ./promotion.jl:302
 [4] +(::MyInt, ::MyInt) at ./int.jl:799
 [5] top-level scope at none:0

```

Can someone help explain this?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 5, 2019, 4:05pm UTC](https://discourse.julialang.org/t/understanding-supertypes/24971/2 "2019-06-05T16:05:08Z")

</div>

You would need to define `Base.+` for `MyInt`. And then for more generic code, some [promotion rules](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#Promotion-1).

Various packages extend eg `Float64`, you should look at them to see how it is done in the wild. `Base.Rational` is a good example (the manual mentions this), and so is eg

> **[GitHub - JuliaMath/DoubleFloats.jl: math with more good bits](https://github.com/JuliaMath/DoubleFloats.jl)**
>
> math with more good bits. Contribute to JuliaMath/DoubleFloats.jl development by creating an account on GitHub.

and similar ones.

---

<div class="post-metadata">

**Author:** ![Paul\_McVay](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_mcvay/32/4307_2.png) [@Paul\_McVay](https://discourse.julialang.org/u/Paul_McVay)\
**Post date:** [June 5, 2019, 4:46pm UTC](https://discourse.julialang.org/t/understanding-supertypes/24971/3 "2019-06-05T16:46:42Z")

</div>

What’s the point of the supertype then? I guess basically I want to create a type that acts exactly like an integer exact for one method I want to define to act my way. Is that not possible with supertypes?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 5, 2019, 4:47pm UTC](https://discourse.julialang.org/t/understanding-supertypes/24971/4 "2019-06-05T16:47:49Z")

</div>

The cryptic error message you’re seeing is because julia defines some fallback methods for basic arithmetic operations:

```julia
+(x::Number, y::Number) = +(promote(x,y)...)
-(x::Number, y::Number) = -(promote(x,y)...)
*(x::Number, y::Number) = *(promote(x,y)...)
/(x::Number, y::Number) = /(promote(x,y)...)

```

So what happened was since there were no methods defined for `+(x::MyInt, y::MyInt)` it fell back on `+(x::Number, y::Number) = +(promote(x,y)...)` since `MyInt <: Number`. These definitions are useful for things like adding real numbers to complex numbers. Ie. when you add a real number to a complex number, you want to make the real number a complex number and then you just need to add two complex numbers. ie.

```julia
julia> promote(1.0, 1 + im)
(1.0 + 0.0im, 1.0 + 1.0im)

```

now we have two complex floats that can be added together.

But we see that

```julia
julia> promote(MyInt(1), MyInt(2))
(MyInt(0x0000000000000001), MyInt(0x0000000000000002))

julia> ans == (MyInt(1), MyInt(2))
true

```

so `promote` doesn’t change the types which led to you receiving a (kinda unhelpful) error message. You can read more about `promote` and it’s friends here: [Conversion and Promotion · The Julia Language](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/index.html)

What you probably want to do is something like

```julia
Base.Int(x::MyInt) = reinterpret(Int, x)
Base.:(+)(x::MyInt, y::MyInt) = MyInt(Int(x) + Int(y))

```

and then

```julia
julia> MyInt(1) + MyInt(2) == MyInt(3)
true

```

* * *

As a general comment though, I suspect you don’t actually want to deal with a primitive type here. You might be better served by something like

```julia
struct MyInt <: Integer
    val::Int 
end 

```

ie. just wrapping an integer in a `struct` and then when you need to do operations on `MyInt` you just do them with `myint.val` instead of using `reinterpret` and bit twiddling. But this is going to be quite dependant on your actual usecase.

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [June 5, 2019, 5:03pm UTC](https://discourse.julialang.org/t/understanding-supertypes/24971/5 "2019-06-05T17:03:34Z")

</div>

> [@Paul\_McVay](#):
>
> What’s the point of the supertype then?

In part just what you’re implying it is, but it is not necessarily guaranteed that every method is defined for newly defined types. This would be impossible without requiring types to have standard fields. In the primitives case here it would be downright dangerous to make too many assumptions.

If a supertype describes an “[interface](https://docs.julialang.org/en/v1.1/manual/interfaces/)” (an orthogonal but related concept) then there is a minimal set of methods that must be defined to ensure there are no method errors. Julia has a number of such interfaces in `Base`, but as far as I know none are documented for basic types such as `Integer`. Considering that there are packages that extend `Number` types, it would indeed be nice if these were better documented, so that it would be more clear how to do what you’re attempting here.

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [June 5, 2019, 7:08pm UTC](https://discourse.julialang.org/t/understanding-supertypes/24971/6 "2019-06-05T19:08:18Z")

</div>

This note is about the use of a Type as a `supertype` when defining a `struct`.

* * *

Let’s select `Integer` to be our exemplar `supertype`.

Here is very simple `struct` that is using `Integer` as its `supertype`.

```julia
struct BehavesLikeAnInteger <: Integer
  value::Int
end

intlike = BehavesLikeAnInteger(5)
# BehavesLikeAnInteger(5)

```

Here is almost the same thing – now gone horribly wrong.

```julia
struct BehavesLikeAnInteger <: Integer
    value::String
end

notatall_intlike = BehavesLikeAnInteger("The marmalade is talking.")

# BehavesLikeAnInteger("The marmalade is talking.")

```

The Type that is used as the `supertype` for a `struct` is how we say:

> “This `struct` of mine embodies the intent that Type evinces/evokes.  
> Moreover, the information that I keep each time that this `struct`  
> is constructed, provides the wherewithall to participate in operations  
> that expect some kind of [are designed to accept an] `Integer`.”

* * *

So the choice of a `supertype` is not bringing to bear the operational  
functionality of the type, rather, it is bringing your `struct` into  
the operational fold of that `supertype`. It is incumbent upon the  
designer of a `struct` with `supertype` to provide the functionality  
necessary for the `struct` “to play well with” extant methods.

Often, this is accomplished by forwarding the method through e.g.  
the `value` field of a `struct`. Here is an example.

```julia
struct BehavesLikeAnInteger <: Integer
    value::Int
end

# iszero(x) returns a Bool, no re-construction is needed
Base.iszero(x::BehavesLikeAnInteger) =
    iszero(x.value)

# abs(x) returns a typeof(x), re-construction is needed
Base.abs(x::BehavesLikeAnInteger) =
    BehavesLikeAnInteger(abs(x.value))

```

This gets tedious very quickly. I wrote `TypedDelegation.jl`  
for just this reason. That package makes type respectful  
delegation through the field[s] of a struct easy to express.  
There are examples of how it is used in the README.md file.

* * *

Another reason to choose a supertype for your struct is that  
the supertype is available for use in guiding multidispatch.

```julia
abstract type VideoGame end
abstract type SinglePlayerGame <: VideoGame end
abstract type MultiPlayerGame <: VideoGame end

struct Pacman <: SinglePlayerGame
    <...>
    player::GamePlayer
end

struct RedDeadRedemption2 <: MultiplayerGame
    <...>
    players::Vector{GamePlayer}
end

function gameplayer(game::SinglePlayerGame, player::GamePlayer) ... end

function gameplayers(game::MultiPlayerGame, players::Vector{GamePlayer}) ... end

```

Register all your players, in one [actually two] fell swoop,  
independent of the specific game being played, dispatched by  
the virtual trait `isita_singleplayergame` implemented through  
inheritance and dispatch.
