Same, I always remember this with interfaces and inheritance, shoehorned in BS where I’m only using 1 class anyway and talking to 1 other class what’s the point of this?
After I graduated as a personal project i made a wiki for a game and I was reusing a lot of code, “huh a parent class would be nice here”.
In my first Job, I don’t know who’s going to use this thing I’m building but these are the rules: proceeds to implement an interface.
When I have to teach these concepts to juniors now, this is how I teach them: inheritance to avoid code duplication, interfaces to tell other people what they need to implement in order to use your stuff.
I wonder why I wasn’t taught it that way. I remember looking at my projects that used this stuff thinking it was just messy rubbish. More importantly, I graduated not understanding this stuff…
I wouldn’t say that inheritance is for avoiding code duplication. It should be used to express “is a” relationship. An example seen in one of my projects: a mixin with error-handling code for a REST service client used for more than one service has log messages tightly coupled to a particular service. That’s exactly because someone thought it was ok to reuse.
In my opinion, inheritance makes sense when you can follow Liskov’s principle. Otherwise you should be careful.
You’re not wrong but I think when you’re teaching someone just having 1 parent and 1 child class makes for a bad example I generally prefer to use something with a lot of different children.
My go-to is exporters. We have the exporter interface, the generic exporter, the accounting exporter and the payroll exporter, to explain it.
At school, the only time I used inheritance was 1 parent (booking) and 1 child (luxury) this is a terrible example imo.
Maybe that example was made terrible because the author couldn’t think of a good ways to show how great this can be. I’m obviously a fan of SOLID, and OCP is exactly why I don’t worry if I have only one class at the beginning. Because I know eventually requirements would change and I’d end up with more classes.
Some time ago I was asked by a less experienced coworker during a code review why I wrote a particularly complex piece of code instead just having a bunch of if statements. Eventually this piece got extended to do several other things, but because it was structured well, extending it was easy with minimum impact for the code-base. This is why design matters.
Above claims are based on nearly 2 decades of writing software, 3/4 of it in big companies with very complex requirements.
I mostly come to prefer composition, this approach apparently even has a wiki page. But that’s in part because I use Rust that forbids inheritance, and don’t have such bullshit (from delegation wiki page):
classA {
voidfoo() {
// "this" also known under the names "current", "me" and "self" in other languagesthis.bar();
}
voidbar() {
print("a.bar");
}
}
classB {
private delegate A a; // delegation linkpublicB(A a) {
this.a = a;
}
voidfoo() {
a.foo(); // call foo() on the a-instance
}
voidbar() {
print("b.bar");
}
}
a = newA();
b = newB(a); // establish delegation between two objects
Calling b.foo() will result in b.bar being printed, since this refers to the original receiver object, b, within the context of a. The resulting ambiguity of this is referred to as object schizophrenia
Translating the implicit this into an explicit parameter, the call (in B, with a a delegate) a.foo() translates to A.foo(b), using the type of a for method resolution, but the delegating object b for the this argument.
Why would one substitute b as this when called from b.a is beyond me, seriously.
Same, I always remember this with interfaces and inheritance, shoehorned in BS where I’m only using 1 class anyway and talking to 1 other class what’s the point of this?
After I graduated as a personal project i made a wiki for a game and I was reusing a lot of code, “huh a parent class would be nice here”.
In my first Job, I don’t know who’s going to use this thing I’m building but these are the rules: proceeds to implement an interface.
When I have to teach these concepts to juniors now, this is how I teach them: inheritance to avoid code duplication, interfaces to tell other people what they need to implement in order to use your stuff.
I wonder why I wasn’t taught it that way. I remember looking at my projects that used this stuff thinking it was just messy rubbish. More importantly, I graduated not understanding this stuff…
I wouldn’t say that inheritance is for avoiding code duplication. It should be used to express “is a” relationship. An example seen in one of my projects: a mixin with error-handling code for a REST service client used for more than one service has log messages tightly coupled to a particular service. That’s exactly because someone thought it was ok to reuse.
In my opinion, inheritance makes sense when you can follow Liskov’s principle. Otherwise you should be careful.
You’re not wrong but I think when you’re teaching someone just having 1 parent and 1 child class makes for a bad example I generally prefer to use something with a lot of different children.
My go-to is exporters. We have the exporter interface, the generic exporter, the accounting exporter and the payroll exporter, to explain it.
At school, the only time I used inheritance was 1 parent (booking) and 1 child (luxury) this is a terrible example imo.
Maybe that example was made terrible because the author couldn’t think of a good ways to show how great this can be. I’m obviously a fan of SOLID, and OCP is exactly why I don’t worry if I have only one class at the beginning. Because I know eventually requirements would change and I’d end up with more classes.
Some time ago I was asked by a less experienced coworker during a code review why I wrote a particularly complex piece of code instead just having a bunch of if statements. Eventually this piece got extended to do several other things, but because it was structured well, extending it was easy with minimum impact for the code-base. This is why design matters.
Above claims are based on nearly 2 decades of writing software, 3/4 of it in big companies with very complex requirements.
What no, inheritance is not for code sharing
Sound bite aside, inheritance is a higher level concept. That it “shares code” is one of several effects.
The simple, plain, decoupled way to share code is the humble function call, i.e. static method in certain langs.
I mostly come to prefer composition, this approach apparently even has a wiki page. But that’s in part because I use Rust that forbids inheritance, and don’t have such bullshit (from delegation wiki page):
Why would one substitute
b
asthis
when called fromb.a
is beyond me, seriously.