►
Description
How not to rely on inheritance
As opposed to many languages, Rust doesn't have a concept of inheritance, relying instead on Traits. In this talk, we'll talk about Traits and how to use them for common programming patterns.
About Valentin Tolmer
I am a craftsman, always working to improve my code and others' around me.
Slides: https://docs.google.com/presentation/d/1qGrhRDUgFrnMsSm4MHO0IGozfSlNomn3mlmktWcvI5M/edit
A
Thank
you
so
yeah,
so
yeah,
I've
been
I've
been
working
on
with
rust
for
side
projects
and
it's
an
honor
and
a
pleasure
to
to
be
able
to
speak
at
this
first
meetup.
Thank
you
for
inviting
me
so
today.
I
would
like
to
share
a
very
crucial,
important
feature
of
rust,
which
is
well.
You
know
it
already
it's
traits.
A
A
So
let's
have
a
look
at
how
we
can
avoid
relying
an
inheritance,
because
not
everyone
has
a
rich
uncle
who
can
conveniently
die
and
leave
you
a
lot
of
money.
How
do
you?
How
do
you
get
by
without
inheritance,
and
how
does
rust
do
it
and
yeah?
Let's,
let's
dive
in
so
there
are
different
approaches
to
the
same
problem.
A
The
core
problem
that
we
have
is
that
we
want
to
write
generic
code.
So
let's
say
that
we
want
to
manipulate
animals
and
all
animals,
at
least
those
that
we
want
to
manipulate,
make
a
sound.
So
if
it's
a
dog,
we
want
it
to
bark.
Otherwise,
if
it's
a
cat,
we
want
it
to
meow.
Otherwise,
if
it's
a
snake,
we
want
it
to
hiss
and
so
on.
A
So
we
could
write
code
like
this.
If
dog
then
bark
else,
if
then
meow,
but
that's
very
repetitive,
you
have
to
list
it
everywhere
that
you
want
to
that.
You
want
them
to
make
a
sound
and
whenever
you
add
a
new
type,
then
suddenly
you
have
to
change
every
new
every
call
site,
because
every
call
site
has
to
handle
the
new
animal
and
also
like,
if
you
want
to
take
an
animal
as
parameter
or
store
it
in
a
collection
or
return
it.
A
What
is
the
type
of
a
dog
or
a
cat
or
a
snake
or
and
so
on,
so
you
could
model
that
within
an
interest,
but
that's
not
what
we're
here
to
talk
about.
So
let's
have
a
look
at
how
java
does
it
so
java?
A
Usually
you
would
write
an
abstract
class
animal
and
you
would
define
a
function
cry
that
is,
that
is
what
animals
do
and
then
you
can
create
a
class
cat
that
extends
animal
that
inherits
from
animal
and
then
implement
that
function
cry
you
don't
have
to
do
it
through
an
abstract
class.
You
can
do
well,
you
could
do
it
through
a
concrete
class,
even
though
it's
usually
bad
style,
or
you
can
do
it
through
an
interface
which
is
a
bit
like
an
abstract
class,
except
that
it
cannot
have
fields.
A
A
Okay,
now,
let's
have
a
look
at
how
c,
plus
plus
does
it.
So
this
is
again
things
that
most
people
know
I'm
just
laying
the
ground
for
what
we're
going
to
compare
it
against.
So
in
c,
plus
plus,
you
would
do
similar
a
similar
thing
to
java.
You
would
have
a
class
animal
that
has
a
virtual
method
that
is
not
implemented
here.
B
A
A
Boundary
between
a
class,
an
abstract
class
and
an
interface,
an
abstract
class
is
only
abstract
because
it
has
a
function
that
is
not
implemented
and
an
interface
is
a
java
concept
that
doesn't
really
translate
to
c,
plus
plus
so
with
multiple
inheritance.
You
can
even
have
trouble
with
the
time
and
inheritance
where
you
inherit
from
two
classes
that
both
inherit
from
the
same
so
from
which
path.
Do
you
get
your
your
inheritance
from
the
top
one?
It's
it
can
become?
It
can
be
complex.
A
A
So,
for
instance,
here
we
have
a
function,
make
it
cry
that
takes
an
animal
and
and
calls
animal
that
cry.
However,
here
I
wrote
a
type
name
animal,
but
I
could
have
written
type
name
t
and
then
take
a
constitutive
because
it
doesn't
the
the
name.
Animal
is
doesn't
mean
anything
there,
it's
just
a
name
for
the
type
and
we
don't
have.
A
A
A
There
is
no
interface
declaration,
it's
going
to
come
in
c
class,
20
with
concepts,
but
it's
not
there
yet,
and
then
this
so
the
templates
are
doing
monomorphization
so
meaning
they
copy
paste
the
function
for
every
type
that
it's
used
with
and
then
inline
the
type
which
makes
a
different
function
for
every
type.
There's
no
one
function
that
handles
every
type.
It's
just
a
copy
of
that
function.
A
Okay,
now
that
the
context
is
set,
let's
have
a
look
at
how
rust
does
it
so
for
us
we
have
traits
so
a
trait.
For
instance,
we
can
introduce
the
trait
animal
that
has
a
function
cry
and
then,
if
we
want
to
implement
a
cat,
then
we
declare
the
cat.
This
is
a
strut,
it
has
fields
or
not
doesn't
matter
and
then
separately
from
the
declaration
of
the
trait
and
the
struct.
A
A
In
summary,
a
risk
trait
declares
an
interface
it's
decoupled
from
the
type
declaration
and
from
the
trait
declaration
a
type
can
implement
multiple
traits
and
traits
don't
have
fields,
they
can
only
have
methods.
So
it's
a
little
bit
like
java
interfaces,
except
that
they
are
used
both
statically
and
dynamically.
A
A
Let
me
point
it
that's
what
the
little
din
keyword
means
and
then
you
can.
You
can
use
animal.cry
and
because
it's
a
it's
a
method
of
animal-
and
here
you
only
know
that
it
implements
the
type
animal
to
trait
animal,
so
you
can
only
use
methods
of
the
trait
animal
so
like
in
c
plus,
you
cannot
receive
the
animal
by
value,
because
animal
is
not
a
concrete
type,
so
you
cannot
copy
it
or
you
can
you
can
you
cannot
move
it?
A
A
A
So
we
have
our
our
function,
get
barn
animal
that
takes
a
barn
and
return
an
animal
from
the
barn.
So
once
again,
you
can
see
that
we're
returning
a
reference
to
a
din
animal,
meaning
we're
returning
a
reference
to
something
that
we
know
implements
the
trait
animal.
But
that's
all
we
know
I
left
some
blanks
in
the
in
the
function
definition,
because
if
you've,
if
you
played
with
the
rest,
a
little
bit
you've
ran
into
this
lifetimes.
A
A
And
yeah,
so
as
an
as
in
taking
arguments,
you
cannot
return
a
value
of
an
animal.
You
have
to
return
a
reference
or
a
box
now
what
if
we
want
to
do
static
dispatch,
so
static
dispatch
is
when
we
know
at
compile.
B
A
A
A
A
And
yeah
and
c
plus
plus
you
can
do
duct,
typing
and
and
use
pretty
much
anything.
A
So
if
you
want
to
return
an
animal
well,
it's
the
same.
If
we
want
to,
we
can
return
by
value.
It's
okay,
because
because
we
know
the
type
of
the
animal
is
the
t
you
can
return
by
value.
A
So
it
has
its
it's
downsides
too,
but
usually
it's
better
to
be
to
do
static
dispatch.
If
you
can
that's
not
always
possible,
for
instance,
if
you
have
a
vector
of
animals,
you
cannot
have
a
vector
of
well.
If
you
have
different
types
of
animals,
then
you
have
to
store
boxes
of
reference
to
them.
A
So
for
for
a
static
dispatch
you
can
you
can
have
a
constraint,
you
can
have
multiple
constraints
on
the
type.
So,
for
instance,
you
can
say
that
t
has
to
be
an
animal
and
a
runner
so
that
you
can
use
both
cry
and
run,
and
you
can
either
specify
the
constraint
when
you
declare
the
type
argument
or
after
declaring
the
the
the
function
and
the
return
type
in
the
constraints
below
it's
just
syntax.
Both
are
equivalent.
A
A
A
Very
simplified
trait
partial
egg,
so
it
has
one
unimplemented
method,
which
is
egg
so
for
equal.
It
takes
the
the
object
and
another
object
of
the
same
type
and
returns
the
boolean,
whether
it's
true
or
false,
and
it
gives
you
for
free.
The
function
n
e,
not
equal,
which
is
by
default,
implemented
as
the
opposite
of
equal
and
there's
some
difference
between
partial
egg.
B
A
Being
that
partial
egg
can
return
false
if
you
pass
twice
the
same
object,
but
an
egg
has
to
has
to
return
true,
if
you
pass
twice
the
same
object
and
we
say
that
egg
is
like
an
inherit
from
partial
like
if
you
want,
as
it
has
the
added
constraint,
that
the
type
has
to
be
partial
egg,
because
it
means
that
to
be
equal
comparable,
you
have
to
be
at
least
partially
equal
equal,
comparable.
A
Let's
not
get
too
deep
into
that.
It's
not
critical.
So,
let's
implement
partial
egg
for
a
type.
Let's
say
you
have
a
strict
url
and
it
has
lots
of
fields
different
ways
to
represent
the
same
thing.
So
once
you
want
to
say
that
two
urls
are
equivalent
or
equal
if
they
have
the
same
canonical
representation,
so
you
will
implement
partial
egg
for
url,
saying
okay,
I
take
I
take
a
url
and
another,
so
self,
with
the
capital.
A
Editor
is
the
type
for
which
we're
implementing
the
trade
so
url
and
then
returning
a
boolean,
true
or
false,
and
we're
just
going
to
compare
the
canonical
representation
of
the
two
urls
and
that
way,
once
you
have
written
this,
you
can
write
everywhere,
url
a
equals.
Your
you
can
check
if
url
a
equals
url
b
without
calling
dot
x,
because
the
compiler
knows
that
you
implemented
partial
x,
so
it
can
unwrap
the
the
the
equal
comparison.
A
A
You
have
you
have
a
you
want
to
say.
The
iterator
has
a
next
function
that
returns
an
option
of
something,
but
the
the
option
of
something.
This
type
is
part
of
the
interface.
So
you
have
to
say
what
is
the
type
that
you're
going
to
return?
A
So
item
is
part
of
the
interface
and
when
you
implement
iterator,
you
have
to
say
what
is
item
so
item
that
can
be
a
regular
integer
or
it
can
be
a
reference
to
to
a
cat,
or
it
can
even
be
a
dynamic
reference
to
an
animal
anything
goes,
but
when
implementing
iterator,
you
have
to
say
what
is
the
item
in
addition
to
implementing
next
and
iterator
comes
with
many
more
functions
that
are
defined
in
terms
of
next.
A
A
Then,
let's
print
with
some
debug
which,
by
the
way,
uses
the
the
debug
trait
we'll
take
from
always
one
we'll
take
the
first
10
items
because
we
implemented
it
so
that
it
never
returns.
None
it's
an
infinite
iterator.
So
we
cannot
just
say,
put
everything
in
a
vector
we'll
take
the
first
10
and
put
that
into
a
vector,
we'll
collect.
A
Them
into
a
vector,
so
when
we
print
this,
it
gives
us
1,
1,
1,
1,
1,
1,
1
and
so
on.
You'll
notice
that
I
didn't
define
the
take
method.
For
always
same.
I
didn't
have
to
it's
an
it's
a
method
from
iterator
that
is
defined
in
terms
of
next.
It
just
calls
next
10
times,
so
it
returns
an
iterator.
It
returns
a
new
iterator
that
will
stop
after
10
times.
A
Okay,
now,
let's
say
that
we're
receiving
a
vector
of
data,
a
vector
of
integer,
and
we
want
to
return
an
iterator
that
takes
only
those
small
numbers,
those
are
inferior
to
three
and
it
will
infinitely
loop
over
them.
A
A
A
A
B
A
A
A
A
A
A
So
you
can
implement
standard
trades
for
your
types.
For
instance,
we
implemented
the
standard,
iterated
trait
or
you
can
implement
your
own
trait
for
standard
types.
You
can
add
methods
to
vector,
but
you
cannot
implement
standard
traits
for
standard
tr
types,
so
you
cannot
implement
a
trait
introduced
in
another
crate
for
a
time
introduced
in
another
crate.
A
So,
for
instance,
you
could
do
some
downcasting,
which
is
instance
of
in
java
or
dynamic,
cast
in
c
plus
plus,
usually
not
something
that
you
want
to
do.
It
usually
means
that
you
don't
have
the
right
attraction
it's
possible
to
do
in
rust,
if
you
add
some
boilerplate
to
the
types
and
so
on,
it's
a
bit
awkward.
Some
crates
make
it
easier,
but
still
not
great.
You
have
to
change
the
definition.
A
You're
getting
an
animal,
so
this
is
a
java
example
you're
receiving
an
animal
you're
checking
if
it's
a
dog
or
a
cat,
then
I
want
to
adopt
it
and
if
it's
a
mosquito,
then
I
want
to
squash
it
well,
so
the
techniques
I'm
about
to
show
were
also
in
java.
It's
just
that
in
rust.
I
want
to
give
you
tools
when
you,
when
you
come
around
along
this
problem,
to
change
the
way
you
think
and
maybe
rephrase
it
reframe
it
in
a
way
that
is
better
suited
for
the
tools
that
russ
gives
you.
A
So
you
could
either
extend
the
trait
animal
and
add
the
function
adoptable.
That
by
default
is
true,
and
then,
when
you
implement
animal
for
mosquito,
you
say
that
adoptable
returns
false
or
you
could
create
a
new
trainees.
You
could
say
that
things
can
be
adoptable
by
default.
They
are
and
mosquitoes
are
not,
but
you
still
have
to
say
that
for
that
cats
are
adoptable
and
dogs
are
adoptable
and
for
every
animal
you
still
have
to
implement
adoptable
as
well.
A
A
So
some
of
the
traits
that
I
presented
so
far
were
you.
You
saw
them,
but
you
never
actually
used
that
you
never
actually
implemented
them
yourself,
for
instance
debug,
partial,
egg
or
egg.
I
doubt
that
you
actually
implemented
them
yourself.
Usually
you
they
have
an
obvious
implementation,
so
you
would
just
write.
Oh
you
just
derived
the
implementation.
From
from
the
structure
you
that
way,
dog
implements,
debug,
partial
leg
and
egg
with.
A
Implementations
and
usually
when
every
field
of
structure
implements
a
trait
you
can
recursively
implement
it
by
calling
it
recursively
on
every
field
and
to
generate
this
implementation.
With
the
drive
macro,
you
can
actually
write
your
own
derived
micro
for
your
own
traits
using
procedural
macros.
I'm
not
going
to
get
into
that
because
that's
a
complex
topic
on
its
own.
A
Another
thing
that
we
kind
of
touched
on
with
partial
egg
and
egg
is
operator
overloading
to
define
what
the
plus
does
you
just
have
to
implement.
The
trait
add
for
self
and
the
right
hand
side
which,
by
default
itself-
and
so
we
could
implement,
add
for
a
cat
say
that
when
we
add
two
cats,
it
returns
an
integer
and
when
we
add
them
like
it,
returns
actually
to
two
you'll
notice
that
I
implemented
it
for
reference
of
cat
and
not
for
cat
itself.
A
You
could
implement
it
for
cat
itself,
but
then
you
would
be
able
you
would
have
to
move
the
value
into
the
the
plus
of
the
addition
operation,
and
that
might
not
be
what
you
want
so,
for
instance,
here
where
we're
adding
twice
the
same
value.
So
we
couldn't
do
that
if
it
was
by
value
we
had
to
do
it
by
reference
I'll
quickly
skip
over
the
deref
trait,
because
it's
not
super
super
important,
but
basically
it's
you.
You
can
specify
what
it
means
to
dereference
a
type.
A
So,
for
instance,
when
you
have
a
man,
you
can
reference
it
into
two
kids
and
hey:
it's
just
two
kids
in
a
trench
coat
and
you
can
pass
a
man
to
a
function
that
that
expects
two
kids,
because
the
compiler
will
just
reference
it
on
its
own.
A
Okay,
so
autotrades
are
traits
that
contain
so
some
traits
contain
no
interface
and
are
used
just
as
marker
traits.
For
instance,
we
saw
that
egg
in
addition
to
partial
egg
was
just
used
as
a
marker
to
say:
oh
and
those
types
have
the
the
strong
equality,
the
strong
equality
constraint.
A
Some
market
traits
are
automatically
implemented
by
the
compiler.
For
instance.
Sized
is
just
means
that
you
we
know,
study
at
compile
time
the
size
of
your
sizing
memory
of
your
object.
A
A
So
in
conclusion,
traits
are
quite
different
from
c
plus,
plus
and
java.
They
resemble
java
as
interfaces
or
c
plus
plus
abstract
class,
with
no
fields,
but
it's
not
quite
the
same.
A
Their
power
comes
from
the
fact
that
the
the
implementation
for
a
type
is
separated
from
both
the
declaration
of
the
type
and
the
declaration
of
the
trait.
A
So
many
things
in
rest
are
implemented
as
traits
and
they're
very
crucial
to
writing.
Idiomatic
crest
and
a
very
nice
advantage
of
traits
is
that
they're
used
both
dynamically
and
statically
for
for
specifying
an
interface.
So
it's
the
same
mechanism
for
both
compile
time
and
runtime.
B
Questions
hi
valentin.
Thank
you
for
this
presentation.
It
was
very
interesting.
I
did
a
little
bit
of
work
in
traits,
but
I
learned
a
lot
of
new
things.
Yes,
there
are
questions
and
if
that's
okay
for
you,
I
will
relay
them
to
you-
is
that?
Okay,
yes,
okay,
there
is
one
question.
Actually
in
the
organizer
team
we
asked
ourselves
you
showed
traits
in
in
conjunction
with
structs.
Only
is
it
possible
to
define
traits
for
other
types
like
enums.
A
B
Okay,
thank
you.
Thank
you
very
much.
The
next
question
comes
from
matthias.
I
will
just
read
it
to
you:
will
we
ever
get
constant
iterators?
He
asks
while
and
loop
can
already
be
used
in
const
functions,
but
four
does
not
yet
work.
I
suppose
that's
also
because
it
uses
iterators
which
are
not
constant.
Do
you
know
more
about
that.
A
B
Okay,
okay,
yeah,
the
the
second
thing
is
also
a
longer
question.
I'm
not
sure
if
you
have
discord
open,
it's
in
the
meetups
channel
vladimir
is
asking
the
only
difference.
I
know
between
generics,
syntax
and
associated
types
is
that
one
cannot
implement
a
trait
with
an
associated
type
multiple
times
for
a
type.
Are
there
any
other
differences,
and
he
brings
also
an
example.
A
So,
yes,
that's
one,
that's
one
key
concept
of
associated
types.
For
instance,
when
you
implement
iterator
for
vector
it
can
only
ever
return
one
type,
so
you
don't
want
to
implement
iterator
of
integer
for
vector
and
integrator
of
string
for
vector,
because
both
don't
make
sense
at
the
same
time.
So
when
you
implement,
actually
you
don't
implement
iterator
for
vector,
vector,
implement
iterator
for
the
iterator
type
returned
by
vector
sorry.
A
So
if
you
had
generics
at
the
at
the
trade
level,
then
you
would
be
able
to
say
iterator
of
integer
for
that
vector
of
string
which
doesn't
make
sense.
So
it's
a
good
point
to
to
point
out
the
I
guess.
Another
key
difference
is
that
you
can
have
default
values
for
for
generics,
but
I'm
not
sure
that's
the
case
for
associated
types.
A
B
B
B
A
This
says
this
is
essentially
what
happens
already,
because
when,
when
you
add
methods
to
to
a
struct,
then
you
say
impul
for
struct,
so
you're
already
doing
an
implementation
block.
That
is
separate
from
the
the
data
declaration
of
what
the
shape
of
the
structure
looks
like
it's
just
that.
Sometimes
you
want
to
have
some
functions
that
are
limited
only
to
a
single
struct,
because
it
doesn't
make
sense
to
have
another
strike,
to
define
them
and
so
you're.
B
At
the
same
time,
I
didn't
look
it
from
that
point
of
view,
but
yeah,
that's
that's
an
interesting
point
of
view.
Yeah.
Thank
you
very
much.
The
next
one
is
another
question,
a
short
one.
You
mentioned
the
diamond
problem.
I
think
you
mentioned
it
with
c
plus,
plus.
A
A
So
yes,
and
no
because
the
thing
is
your
traits
cannot
override
the
methods
of
another
trait.
Basically
traits
are
just
here
for
the
interface.
A
So
if
you
get
the
interface
from
two
different
traits,
it's
okay,
what
the
problem
in
c
plus
plus,
is
that
the
in
the
diamond,
the
two
classes
in
the
middle
can
implement
the
class
at
the
top
in
different
ways.
A
In
rust,
you
can
have
a
diamond
trait
implementation.
If
you
could
say,
except
that
it's
not
really
a
diamond
you
don't
when
a
trait
inherits
from
another.
It
just
means
that
it
requires
the
class
that
implements
it
to
also
implement
the
super
trait.
So
egg
doesn't
inherit
from
partial
egg
in
the
way
that,
if
you're,
if
you
were
to
somehow
just
implement
egg,
you
don't
get
the
the
the
dot
egg
and
dot
any
methods,
it's
just
that
to
implement
egg.
You
have
to
implement
partial
egg.
A
B
Yeah,
that's
clear,
I
think
you
described
it
very
well.
I
could
understand
it
and
I
hope
the
question
was
answered
with
that.
Let
me
quickly
check
whether
we
have
something
in
the
chat.
No,
I
think
that
chat
is
empty
and
meetups
and
technical
discussion
yeah.
I
think
you
answered
all
the
question.
Let
me
quickly
ask
the
the
crowd
whether
where
we
have
additional
questions,
this
is
your
last
chance
to
ask
your
questions
live
while.
B
A
Just
want
to
to
say
I'm
coming
back
to
the
the
concentrator
question
yeah,
so
I
don't
know
specifically
about
const,
but
something
that
I
didn't
mention
about.
The
iterator
trait.
Is
that
it's
what
powers
the
for
loops.
So
when
you
say
for
a
in
a
vector
what
happens
behind
is
that
we
there's
an
into
iterator
trait,
that
turns
the
vector
into
an
iterator,
and
then
we
iterate
over
that
with
the
dot
next,
and
so
all
of
that
is
just
syntactic
sugar
provided
over
the
iterator
trait.
B
Thank
you
very
much.
Thank
you
for
pointing
that
out.
I
would
like
to
point
out
for
people
who
are
watching
on
youtube,
and
I
know
there
are
some
people
watching
on
youtube
there.
We
don't
use
the
discussion
on
youtube.
If
you
want
to
ask
questions,
please
come
to
our
discord
server
and
ask
your
questions
there.
We
will
relay
them
to
our
speakers.
B
Valentine
I
think
we
are
through.
I
don't
have
any
more
open
questions.
Thank
you
very
much
for
this
great
talk.
I
learned
a
lot
and
I'm
pretty
sure
that
it
was
very
interesting
for
many
of
our
viewers.
It
was
a
pleasure
having
you
here
and
we
hope
that
you
also
enjoyed
giving
this
presentation
here
at
the
rosslyn
meetup.
A
Thank
you
for
inviting
me
it
was
was
very
nice.
It
was
my
first
time
doing
a
presentation
without
seeing
the
audience,
so
that
was
interesting,
but
it
was
a
great
opportunity
and
thank
you
very
much.