Traits
Rust traits are more akin to Perl roles; they describe "does-a" rather than "is-a" relationships.
If we define a role like this in Perl
package Area {
use Role::Tiny;
requires qw(area);
}
then anything that does the Area
role must have a method called area
.
Similary, if we define a trait like this in Rust
#![allow(unused_variables)] fn main() { trait Area { fn area(&self) -> f64; } }
then anything that implements the Area
trait, must have a method called area
with that exact function signature.
For example, in Perl we could create a Circle and a Rectangle that both do the Area role like so
#!/usr/bin/env perl
use v5.28;
use warnings;
use experimental qw(signatures);
package Area {
use Role::Tiny;
requires qw(area);
}
package Circle {
use Role::Tiny::With;
with 'Area';
sub new($class, $radius) {
my $self = {
_radius => $radius,
};
bless $self, $class;
return $self;
}
sub area($self) {
3.14159265358979 * $self->{_radius} ** 2
}
}
package Rectangle {
use Role::Tiny::With;
with 'Area';
sub new($class, $length, $width) {
my $self = {
_length => $length,
_width => $width,
};
bless $self, $class;
return $self;
}
sub area($self) {
$self->{_length} * $self->{_width}
}
}
my $c = Circle->new(1);
say "Area of circle is ", $c->area;
my $r = Rectangle->new(2, 3);
say "Area of rectangle is ", $r->area;
Alternatively, here it is again using Perl's Object::Pad.
Similarly, in Rust we could create a Circle and a Rectangle that both implement the Area trait like so
trait Area { fn area(&self) -> f64; } struct Circle { radius: f64, } impl Circle { fn new(radius: f64) -> Self { Self{radius} } } impl Area for Circle { fn area(&self) -> f64 { std::f64::consts::PI * self.radius.powi(2) } } struct Rectangle { length: f64, width: f64, } impl Rectangle { fn new(length: f64, width: f64) -> Self { Self{length, width} } } impl Area for Rectangle { fn area(&self) -> f64 { self.length * self.width } } fn main() { let c = Circle::new(1.0); println!("Area of circle is {}", c.area()); let r = Rectangle::new(2.0, 3.0); println!("Area of rectangle is {}", r.area()); }
Running either of these produces
Area of circle is 3.14159265358979
Area of rectangle is 6
There's more to Rust's traits (they're sort of the key to all of the magic in Rust), but that'll do for now.