72dcddcac70043663e27f56d38b864d74536a51a
[rust-101.git] / src / part02.rs
1 // Rust-101, Part 02: Generic types (WIP)
2 // ================================
3
4 use std;
5
6 // Let us for a moment reconsider the type `NumberOrNothing`. Isn't it a bit
7 // annoying that we had to hard-code the type `i32` in there? What if tomorrow,
8 // we want a `CharOrNothing`, and later a `FloatOrNothing`? Certainly we don't
9 // want to re-write the type and all its inherent methods.
10
11 // The solution to this is called *generics* or *polymorphism* (the latter is Greek,
12 // meaning "many shapes"). You may know something similar from C++ (where it's called
13 // *templates*) or Java, or one of the many functional languages. So here, we define
14 // a generic `SomethingOrNothing` type.
15 enum SomethingOrNothing<T>  {
16     Something(T),
17     Nothing,
18 }
19 use self::SomethingOrNothing::{Something,Nothing};
20 // What this does is to define an entire family of types: We can now write
21 // `SomethingOrNothing<i32>` to get back our `NumberOrNothing`, but we
22 // can also write `SomethingOrNothing<bool>` or even `SomethingOrNothing<SomethingOrNothing<i32>>`.
23 // In fact, such a type is so useful that it is already present in the standard
24 // library: It's called an *option type*, written `Option<T>`.
25 // Go check out its [documentation](http://doc.rust-lang.org/stable/std/option/index.html)!
26 // (And don't worry, there's indeed lots of material mentioned there that we did not cover yet.)
27
28 // **Exercise**: Write functions converting between `SomethingOrNothing<T>` and `Option<T>`. You will have to use
29 // the names of the constructor of `Option`, which you can find in the documentation I linked above.
30
31 // Here's a skeleton for your solution, you only have to fill in the function bodies.
32 // (`panic!` is, again, a macro - this one terminates execution when it is reached).
33 // 
34 // Notice the syntax for giving generic implementations to generic types: Think of the first `<T>` 
35 // as *declaring* a type variable ("I am doing something for all types `T`"), and the second `<T>` as
36 // *using* that variable ("The thing I do, is implement `SomethingOrNothing<T>`").
37 impl<T> SomethingOrNothing<T> {
38     fn new(o: Option<T>) -> Self {
39         panic!("Not yet implemented.");
40     }
41
42     fn to_option(self) -> Option<T> {
43         panic!("Not yet implemented.");
44     }
45 }
46 // Inside an `impl`, `Self` refers to the type we are implementing things for. Here, it is
47 // an alias for `SomethingOrNothing<T>`.
48 // Remember that `self` is the `this` of Rust, and implicitly has type `Self`.
49 // 
50 // Observe how `new` does *not* have a `self` parameter. This corresponds to a `static` method
51 // in Java or C++. In fact, `new` is the Rust convention for defining constructors: They are
52 // nothing special, just static functions returning `Self`.
53
54 // You can call static functions, and in particular constructors, as follows:
55 fn call_constructor(x: i32) -> SomethingOrNothing<i32> {
56     SomethingOrNothing::new(Some(x))
57 }
58     
59
60 // [index](main.html) | [previous](part01.html) | next