Traits
Traits are the way to do object-oriented programming in the Fuse programming language, They are similar to interfaces in the fact that they enforce a certain representation and set of methods on our objects. A trait
has a key difference with an interface and that is a trait that doesn’t create a type. While both are used interchangeably we should keep in mind that traits are a compile-time concept and will get copied instead of inherited.
We can define a trait this way:
trait Pet
fn name(self) -> string
fn birthday(self) -> Date
fn play(self) -> string
end
Note: All methods defined in a trait
are implicitly marked as public.
Now we can create 2 animal types called Dog
and Cat
, With the trait Pet
implemented for them.
struct Dog
name: string
end
struct Cat
name: string
end
impl Pet for Dog
fn name(self) => self.name
fn play(self)
'${self.name()} says "Bark"'
end
end
impl Pet for Cat
fn name(self) => self.name
fn play(self)
'${self.name()} says "Pur"'
end
end
Now that we have 2 structures implementing the same trait we need a way to reference them or pass them into functions as arguments, But if you remember traits don’t actually create a type, and therefore we have no knowledge of them at the runtime. However we still can use them as types to refer to a value that implements the said trait, This happens thanks to the dynamic dispatching and garbage collected nature of the language. While the use of a trait is natural for record types such as struct and table, It will force the compiler to box the primitives when they are treated like a dynamic reference type.
fn pet(p: Pet)
print(p.play())
end
let dog = Dog { name: "George" }
let cat = Cat { name: "Amy" }
-- we can pass both the dog and cat as their trait type
pet(dog)
pet(cat)
-- we can also reduce their type and store them as their trait
let my_pet: impl Pet = dog as Pet
When we assign a variable to an impl trait
type we erase the type information about the said object. The only way to retrieve the initial type back is through a cast which doesn’t provide compile-time checks.
let pet1: impl Pet = dog as Pet
let pet2: impl Pet = cat as Pet
let mut my_dog: Dog = pet1 as Dog -- this will compile and run successfully
my_dog = pet2 as Dog -- this will also compile but will panic at runtime
- Previous
- Next