Skip to content

Commit

Permalink
Merge pull request #1259 from adamchalmers/supertraits
Browse files Browse the repository at this point in the history
Fix #90: Add supertraits and Fully Qualified syntax
  • Loading branch information
marioidival authored Sep 18, 2019
2 parents fae4db2 + c860ab8 commit 67cfbf3
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@
- [Iterators](trait/iter.md)
- [`impl Trait`](trait/impl_trait.md)
- [Clone](trait/clone.md)
- [Supertraits](traits/supertraits.md)
- [Disambiguating overlapping traits](traits/disambiguating.md)

- [macro_rules!](macros.md)
- [Syntax](macros/syntax.md)
Expand Down
62 changes: 62 additions & 0 deletions src/traits/disambiguating.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Disambiguating overlapping traits

A type can implement many different traits. What if two traits both require the same name? For example, many traits might have a method named `get()`. They might even have different return types!

Good news: because each trait implementation gets its own `impl` block, it's
clear which trait's `get` method you're implementing.

What about when it comes time to _call_ those methods? To disambiguate between
them, we have to use Fully Qualified Syntax.

```rust,editable
trait UsernameWidget {
// Get the selected username out of this widget
fn get(&self) -> String;
}
trait AgeWidget {
// Get the selected age out of this widget
fn get(&self) -> u8;
}
// A form with both a UsernameWidget and an AgeWidget
struct Form {
username: String,
age: u8,
}
impl UsernameWidget for Form {
fn get(&self) -> String {
self.username.clone()
}
}
impl AgeWidget for Form {
fn get(&self) -> u8 {
self.age
}
}
fn main() {
let form = Form{
username: "rustacean".to_owned(),
age: 28,
};
// If you uncomment this line, you'll get an error saying
// "multiple `get` found". Because, after all, there are multiple methods
// named `get`.
// println!("{}", form.get());
let username = <Form as UsernameWidget>::get(&form);
assert_eq!("rustacean".to_owned(), username);
let age = <Form as AgeWidget>::get(&form);
assert_eq!(28, age);
}
```

### See also:

[The Rust Programming Language chapter on Fully Qualified syntax][trpl_fqsyntax]

[trpl_fqsyntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name
43 changes: 43 additions & 0 deletions src/traits/supertraits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Supertraits

Rust doesn't have "inheritance", but you can define a trait as being a superset
of another trait. For example:

```rust,editable
trait Person {
fn name(&self) -> String;
}
// Student is a supertrait of Person.
// Implementing Student requires you to also impl Person.
trait Student: Person {
fn university(&self) -> String;
}
trait Programmer {
fn fav_language(&self) -> String;
}
// CompSciStudent (computer science student) is a supertrait of both Programmer
// and Student. Implementing CompSciStudent requires you to impl both subtraits.
trait CompSciStudent: Programmer + Student {
fn git_username(&self) -> String;
}
fn comp_sci_student_greeting(student: &dyn CompSciStudent) -> String {
format!(
"My name is {} and I attend {}. My Git username is {}",
student.name(),
student.university(),
student.git_username()
)
}
fn main() {}
```

### See also:

[The Rust Programming Language chapter on supertraits][trpl_supertraits]

[trpl_supertraits]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-supertraits-to-require-one-traits-functionality-within-another-trait

0 comments on commit 67cfbf3

Please sign in to comment.