## Traits Are Interface Types

• Define methods, fields and types that must be present in the implementation of a struct or enum

• Principal mechanism for code reuse in Rust

• Interact strongly with and enhance "generic" types (parametric polymorphism)

## Misc Trait Things

• Traits and scope control

• Subtraits

• This is an "easy, boring" chapter

• There are traits that can be used to tell the Rust compiler to use standard operators for your standard type

## What You Cannot (Must Not) Do

• Cannot change precedence or associativity of standard operators

• Overloaded operators are "expected" (not required, but really?) to obey basic arithmetic laws "as appropriate", for example

• Associativity of *

a * (b * c) == (a * b) * c

• Transitivity of inequality

a < b < c ⇒ a < c

• In general, it is good style to not be polymorphic with operators, e.g. 1.0 + 2 should maybe be rejected

## What You Can Do

• Pick any operator from the table in the chapter and specify its function on your own datatypes

https://play.rust-lang.org/?gist=c595ec69bf3e6522765b01f6a460a819

• The arithmetic operators consume their arguments. Sorry. Usually derive Copy for arithmetics

• Compound assignment operators are separate. They should be derivable, but currently aren't

• Index and IndexMut allow overloading [] in various contexts. IndexMut requires producing a value, which is borked for types that want to do an initial assignment

## Trait Garbage Bag

• There are a bunch of traits tied into Rust's internals or standard library with no real organizing principle

## Clone

• The Clone trait provides the clone() and clone_from() functions

• clone_from() is little-used: check out the implementation to understand one reason why.

• A Clone implementation should do a "deep copy"

• Clone is usually derived, but see e.g.

http://github.com/BartMassey/sivec

## Marker Traits

• "Marker traits" are a communication channel between compiled code and the compiler

• You can use a marker trait like any other trait

• Marker traits can be ignored, e.g. ?Sized

## Copy

• Copy is a marker trait that you implement when you want your values to be automatically copied by the compiler. It has no methods

• Copy provides Clone for free

• Use Copy sparingly:

• Makes the implementation be careful
• Expensive
• Semantics sometimes surprising

## Drop

• You can implement the Drop trait to get control of a value right before it is freed

• This is used for e.g. closing files, flushing data, etc

• A type implementing Copy cannot also implement Drop, because the semantics are too confusing

## Sized

• Sized is a marker trait that says that the compiler knows the size of values of the type

• You cannot implement Sized yourself

• By default, generic types implicitly require instantiation with something Sized

• You can turn this off with + ?Sized ("questionably sized") in situations where you don't want it

## Deref, DerefMut

• Used to transfer a * dereference of a type to some type in the inner structure

• Canonical cases are Box and similar containers

## Default

• Trait to provide a "default value" for your type

• Be careful: you need to know how things are going to default to know what to expect.

## AsRef, AsMut

• Annoying Rust shorthand: "refmut" is usually just spelled "mut"

• Traits for borrowing a reference to your type from a variety of values

• Usually used for generic parameters. Book says

  fn open<P: AsRef<Path>>(path: P) -> ... {
let path = path.as_ref()
...


## Borrow, BorrowMut

• Identical to AsRef, AsMut ?!?

• By convention, implement for a type only when references are semi-interchangeable with values

• Mostly for collection type convenience

• This is where the types start to get truly ugly: see the book example

## From, Into

• Type conversion traits

• Not really needed, but convenient convention

• Into is just From with the types reversed

• Normally just implement From to get a default implementation of Into

• from() and into() consume their arguments

• from() and into() can only fail by panic(); TryFrom and TryInto are in nightly

## ToOwned

• Trait for "cloning" a thing that implements the Borrow trait

• One standard way to create a String from an &str:

  "hello".to_owned()

• Also works for slice to Vec

## Cow

• "Copy On Write": keeps a reference until owned

• Glory in the beauty of this: book says

  enum Cow<'a, B: ?Sized + 'a>
where B: ToOwned
{
Borrowed(&'a B),
Owned(<B as ToOwned>::Owned),
}


## Observations

• There's a lot of stuff here

• Read this chapter carefully, then…

• Return to it as you advance in Rust. The details are best appreciated in the context of a problem you are trying to solve

• The result of this mess is a pretty expressive language: much is "hidden under the hood"