Using a constructor pattern

No method overloading means that we can only define one new function (which is optional anyway). We could invent different names for our constructors, which is good from the point of view of code documentation. This is demonstrated in the following example:

// see code in Chapter 6/code/constructor_pattern.rs 
struct Alien { 
    name: &'static str, 
    health: u32, 
    damage: u32 
} 
 
impl Alien { 
    fn new(s: &'static str, mut h: u32, d: u32) -> Self { 
        if h > 100 { h = 100; } 
        Alien { name: s, health: h, damage: d } 
    } 
 
    pub fn default() -> Self { 
        Alien::new("Walker", 100, 10) 
    } 
     
    pub fn give_health(h: u32) -> Self { 
        Alien::new("Zombie", h, 5) 
    } 
}    
 
fn main() { 
    let al1 = Alien{ name: "Bork", health: 100, damage: 5 }; 
    let al2 = Alien::new("Berserk", 150, 15); 
    println!("Alien 1 is a {} and inflicts {} damage points", al1.name, al1.damage); 
    let al3 = Alien::default(); 
    println!("Alien 3 is a {} and inflicts {} damage points", al3.name, al3.damage); 
    let al4 = Alien::give_health(75); 
    println!("Alien 4 is a {} and inflicts {} damage points", al4.name, al4.damage); 
 } 

This prints out the following output:

    Alien 1 is a Bork and inflicts 5 damage points
    Alien 3 is a Walker and inflicts 10 damage points
    Alien 4 is a Zombie and inflicts 5 damage points  

Here our new constructor is not public, so an Alien implementor cannot be constructed in code that uses our code. But the default() and give_health() methods are public (indicated by the keyword pub, as in pub fn default()), so external code is restricted in creating either a default Walker or a Zombie with a given health amount.

We see that all three constructors return a Self type, which is the Alien struct type in our context.

Another way to go is called the builder pattern, which we discuss in the following section.