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: 'moo'
}
// 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:
Animal
implementationsing(Cow("moo"))
I do get an error, but at the function sing
!:
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?
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{}