fn main() {

let ix = Person {
        name: "Isus".to_string(),
        age: 2018,
    };
    ix.say_hello();
    hello(ix);
}

// we can call this function with parameter
// of any type that implemens `Hello` trait
fn hello(someone: impl Hello) {
    someone.say_hello();
}

trait Hello {
    // should be implemented
    fn format_hello(&self) -> String;

    // have default implementaion
    fn say_hello(&self) {
        println!("{}", &self.format_hello());
    }
}

struct Person {
    name: String,
    age: i32,
}

impl Hello for Person {
    fn format_hello(&self) -> String {
        return format!("Hi, my name is {}, I'm {} years old.", self.name, self.age);
    }
}