Is it possible for one struct to extend an existing struct, keeping all the fields?

There is nothing that exactly matches that. There are two concepts that come to mind.

  1. Structural composition

    struct Person {
        age: u8,
    }
    
    struct Child {
        person: Person,
        has_toy: bool,
    }
    
    impl Person {
        fn new(age: u8) -> Self {
            Person { age: age }
        }
    
        fn age(&self) -> u8 {
            self.age
        }
    }
    
    impl Child {
        fn new(age: u8, has_toy: bool) -> Self {
            Child { person: Person::new(age), has_toy: has_toy }
        }
    
        fn age(&self) -> u8 {
            self.person.age()
        }
    }
    
    fn main() {
        let p = Person::new(42);
        let c = Child::new(7, true);
    
        println!("I am {}", p.age());
        println!("My child is {}", c.age());
    }
    

    You can simply embed one struct into another. The memory layout is nice and compact, but you have to manually delegate all the methods from Person to Child or lend out a &Person.

  2. Traits

    trait SayHi {
        fn say_hi(&self);
    }
    
    struct Person {
        age: u8,
    }
    
    struct Child {
        age: u8,
        has_toy: bool,
    }
    
    impl SayHi for Person {
        fn say_hi(&self) {
            println!("Greetings. I am {}", self.age)
        }
    }
    
    impl SayHi for Child {
        fn say_hi(&self) {
            if self.has_toy {
                println!("I'm only {}, but I have a toy!", self.age)
            } else {
                println!("I'm only {}, and I don't even have a toy!", self.age)
            }
        }
    }
    
    fn greet<T>(thing: T)
        where T: SayHi
    {
        thing.say_hi()
    }
    
    fn main() {
        let p = Person { age: 42 };
        let c = Child { age: 7, has_toy: true };
    
        greet(p);
        greet(c);
    }
    

You can combine these two concepts, of course.


As DK. mentions, you could choose to implement Deref or DerefMut. However, I do not agree that these traits should be used in this manner. My argument is akin to the argument that using classical object-oriented inheritance simply for code reuse is the wrong thing. "Favor composition over inheritance" => "favor composition over Deref". However, I do hold out hope for a language feature that enables succinct delegation, reducing the annoyance of composition.


Rust does not have struct inheritance of any kind. If you want StructB to contain the same fields as StructA, then you need to use composition.

struct StructB {
    a: StructA,
    // other fields...
}

Also, to clarify, traits are only able to define methods and associated types; they cannot define fields.

If you want to be able to use a StructB as a StructA, you can get some of the way there by implementing the Deref and DerefMut traits, which will allow the compiler to implicitly cast pointers to StructBs to pointers to StructAs:

struct StructA;

impl StructA {
    fn name(&self) -> &'static str {
        "Anna"
    }
}

struct StructB {
    a: StructA, 
    // other fields...
}

impl std::ops::Deref for StructB {
    type Target = StructA;
    fn deref(&self) -> &Self::Target {
        &self.a
    }
}

fn main() {
    let b = StructB { a: StructA };
    println!("{}", b.name());
}