Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #90: Add supertraits and Fully Qualified syntax #1259

Merged
merged 1 commit into from Sep 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/SUMMARY.md
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
@@ -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
@@ -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