A multiple-dispatch example

Let's now explore an example about people working in a company to show multiple dispatch in action. Let's define an abstract type Employee and a type Developer that is a subtype:

abstract type Employee
end

mutable struct Developer <: Employee
name::String
iq
favorite_lang::String
end

We cannot make objects from an abstract type: calling Employee() only returns an ERROR: MethodError: no constructors have been defined for Employee error message.

The type Developer has two implicit constructors, but we can define another outer constructor, which uses a default constructor as follows:

Developer(name, iq) = Developer(name, iq, "Java")

Outer constructors provide additional convenient methods to construct objects. Now, we can make the following two developer objects:

  • devel1 = Developer("Bob", 110), which returns Developer("Bob",110,"Java")

  • devel2 = Developer("William", 145, "Julia"), which returns Developer("William",145,"Julia")

Similarly, we can define a type Manager and an instance of it as follows:

mutable struct Manager
name::String
iq
department::String
end
man1 = Manager("Julia", 120, "ICT")

Concrete types, such as Developer or Manager, cannot be subtyped:

mutable struct MobileDeveloper <: Developer 
platform
end

This returns ERROR: invalid subtyping in definition of MobileDeveloper.

If we now define a function cleverness as cleverness(emp::Employee) = emp.iq, then cleverness(devel1) returns 110, but cleverness(man1) returns an ERROR: MethodError: `cleverness` has no method matching cleverness(::Manager) error message; the function has no method for a manager.

The following function makes us think that managers are always cleverer, which is, of course, not true:

function cleverer(m::Manager, e::Employee)
println("The manager $(m.name) is cleverer!")
end

cleverer(man1, devel1) #> The manager Julia is cleverer!
cleverer(man1, devel2) #> The manager Julia is cleverer!

Suppose we introduce a function cleverer with the following argument types:

function cleverer(d::Developer, e::Employee)
println("The developer $(d.name) is cleverer I think!")
end

The cleverer(devel1, devel2) call will now print "The developer Bob is cleverer I think!". (Clearly, the function isn't yet coded right.) It matches a method because devel2 is also an employee.

However, cleverer(devel1, man1) will give an ERROR: MethodError: `cleverer` has no method matching cleverer(::Developer,::Manager) error message, as a manager is not an employee, and a method with this signature was not defined.

We should now define another method for cleverer as follows:

function cleverer(e::Employee, d::Developer)
if e.iq <= d.iq
println("The developer $(d.name) is cleverer!")
else
println("The employee $(e.name) is cleverer!")
end
end

If we now call cleverer(devel1, devel2) an ambiguity arises; Julia detects a problem in the definitions and gives us the following error:

#> ERROR: MethodError: cleverer(::Developer, ::Developer) is ambiguous. Candidates:
cleverer(e::Employee, d::Developer) in Main at REPL[32]:2
cleverer(d::Developer, e::Employee) in Main at REPL[29]:2
Possible fix, define
cleverer(::Developer, ::Developer)

The ambiguity is that, if cleverer is called with e being a Developer, which of the two defined methods should be chosen? To remove this ambiguity, we will now define the more specific (and correct) method, as follows:

function cleverer(d1::Developer, d2::Developer)
if d1.iq <= d2.iq
println("The developer $(d2.name) is cleverer!")
else
println("The developer $(d1.name) is cleverer!")
end
end

Now, cleverer(devel1, devel2) prints "The developer William is cleverer!" as well as cleverer(devel2, devel1).This illustrates multiple dispatching. When defined, the more specific method definition (here, the second method cleverer) is chosen; more specific means the method with more specialized type annotations for its arguments. More specialized doesn't only mean subtypes, it can also mean using type aliases.


Always avoid method ambiguities by specifying an appropriate method for the intersection case.
..................Content has been hidden....................

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