I'm still trying to wrap my head around Julia's types. For example assuming I wanted to define the structure of an Animal
object. Taking as example typescript I would do something like this:
interface Animal {
sound: string;
}
function sing(animal: Animal) {
console.log(animal.sound);
}
const dog: Animal = {
sound: 'woof',
};
// OR
class Dog implements Animal {
sound = 'woof';
// other Dog methods here
run() {}
}
// Wrong implementations are caught immediately
const cow: Animal = {
noise: 'bark'
}
// Error: Type '{ noise: string; }' is not assignable to type 'Animal'.
// Object literal may only specify known properties, and 'noise' does not exist in type 'Animal'.
How can I do this in Julia? In other words, Animal
needs to have a .sound
. This is what I tried:
abstract type Animal end
function sing(animal::Animal)
println(animal.sound)
end
struct Dog <: Animal
sound::AbstractString
end
function run(dog::Dog) end
struct Cow <: Animal
noise::AbstractString
end
But:
- I don't get any warning from IDE that sing will not work with all the
Animal
implementation - When I try to run
sing(Cow("moo"))
I do get an error, but at the functionsing
!:ERROR: type Cow has no field sound
What am I missing? How can I maintain a large codebase if I get no warning before runtime? How can I define behaviour since I can't subtype concrete classes?
CodePudding user response:
Julia is not object oriented so taking OO is usually not comfortable.
Most often you will want to use multiple dispatch to define behavior for different object types eg.:
abstract type Animal end
getsound(::T) where T <: Animal = throw(ErrorException("not implemented for $T"))
struct Dog <: Animal end
struct Cow <: Animal end
struct Cat <: Animal
specialsound::String
end
getsound(::Dog) = "hau"
getsound(cat::Cat) = cat.specialsound
sing(animal::Animal) = println(getsound(animal))
And here is the usage:
julia> sing(Dog())
hau
julia> sing(Cat("mew"))
mew
julia> sing(Cow())
ERROR: not implemented for Cow
Now regarding IDE - commenting out getsound(::T)
in VS Codium does not underline the cow. However this indeed looks like something that could be added as compiler detects this as an error (assuming getsound(::T) where T <: Animal
is not defined) :
julia> @code_typed sing(Cow())
CodeInfo(
1 ─ Main.getsound(animal)::Union{}
└── unreachable
) => Union{}