Why not inheritance?


#1

Probably this proposal was considered and rejected long ago. I have base class (pseudo-code):

Widget{
  position
  size
  background color
  base methods
}

TreeView {
  w: Widget;
  things specified to TreeView;
}

Window {
  w: Widget;
  things specified to Window;
}

I must call win.w.size. It is would be possible syntax sugar to calling win.size instead indirect by field w?


3 weeks to delegation! Please help
#2

You might want to check out this topic, which answers kind of the same question: Why not just add classes?

Now to answer your question of whether there exists a syntax sugar for forwarding to functions on your base type: The Deref pattern might be what you’re looking for.


#3

What we’re considering along these lines is something like this (syntax may vary):

trait Widget {
    struct {
        position: Position,
        size: Size,
        bgcolor: Color,
    }
    // methods
}

That is, allowing traits to define fields as well methods. We’re also considering sugars for ‘delegation’ as you’ve described, so that your types could all delegate their Widget trait impl to their Widget struct they have. Together these would give you inheritance.


#4

Inheritance is sometimes handy. But given the army of programmers that know OOP and inheritance, what’s stopping them to use that feature as first solution to lot of coding design problems?


#5

By breaking inheritance into its components, you are unlikely to reach for all of it immediately, but just the parts you need:

  • Traits give you polymorphic abstractions.
  • Delegation gives you sugar for types which use the same trait impl.
  • Trait objects give you dynamic dispatch.

You’re not going to immediately reach for all of these things, because they’re all individual choices and not an extremely accessible “this inherits from that” mechanism. But they allow you to express inheritance as a pattern, emergent from our other language features, for situations where you need it.


#6

I was recently playing around with sub-types and inheritance and created this gist that shows off one way to produce most of the effects in a static setting. With near-minimal code you can handle functions that can’t/can/must be overloaded, along with additional data and unique functions.

I assume trait objects could make it all dynamic, but I generally work with static code and don’t know the issues involved.


#7

Thanks for that, that’s interesting! Probably not the most natural way to design things in Rust, but I’m currently struggling to port a piece of C++ code to Rust that makes heavy use of inheritance to reuse code+data across sub-classes, and that might help me…