-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1259 from adamchalmers/supertraits
Fix #90: Add supertraits and Fully Qualified syntax
- Loading branch information
Showing
3 changed files
with
107 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |