Matching to the narrowest types

As discussed in Chapter 2, Modules, Packages, and Data Type Concepts, we can define functions that take abstract types as arguments. When it comes to dispatch, Julia will find the method that matches the narrowest type in the arguments.

To illustrate this concept, let's return to our favorite example in this chapter regarding spaceships and asteroids! In fact, we will improve our data types as follows:

# A thing is anything that exist in the universe.
# Concrete type of Thing should always have the following fields:
# 1. position
# 2. size
abstract type Thing end

# Functions that are applied for all Thing's
position(t::Thing) = t.position
size(t::Thing) = t.size
shape(t::Thing) = :unknown

Here, we have defined an abstract type, Thing, which can be anything that exists in the universe. When we design this type, we expect its concrete subtypes will have the standard position and size fields. Therefore, we just happily define position and size functions for Thing. By default, we do not want to assume any shape of anything, so the shape function for Thing only returns an :unknown symbol. 

To make things more interesting, we will equip our spaceships with two types of weapon—laser and missiles. In Julia, we can conveniently define them as enums:

# Type of weapons
@enum Weapon Laser Missile

Here, the @enum macro defines a new type called Weapon. The only values of the Weapon type are Laser and Missile. Enums are a good way to define typed constants. Internally, they define numeric values for each constant, and so it should be quite performant.

Now, we can define the Spaceship and Asteroid concrete types as follows:

# Spaceship 
struct Spaceship <: Thing
position::Position
size::Size
weapon::Weapon
end
shape(s::Spaceship) = :saucer

# Asteroid
struct Asteroid <: Thing
position::Position
size::Size
end

Note that both Spaceship and Asteroid include position and size fields as part of our design contract. In addition, we have a weapon field added for the Spaceship type. Because we have designed our state-of-the-art spaceships like saucers, we have defined the shape function for the Spaceship type as well. Let's test it out:

We have now created two spaceships and two asteroids. Let's turn our focus to the results of the preceding shape function calls for a moment. When it was called with a spaceship object s1, it was dispatched to shape(s::Spaceship) and returned :saucer. When it was called with an asteroid object, it was dispatched to shape(t::Thing) because there are no other matches for the Asteroid object.

To recap, Julia's dispatch mechanism always looks for the function with the narrowest type in the arguments. Judging between shape(s::Spaceship) and shape(t:Thing), it will choose to execute shape(s::Spaceship) for a Spaceship argument.

Are you familiar with multiple dispatch? If not, don't worry. In the next section, we will dive deep into how multiple dispatch works in Julia.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.67.22