Over time you'll get a better sense of which methods or properties ought to be overloaded, and how/when to invoke super(). So it's best to think of polymorphism as residing in gradations, best applied infrequently.
Honestly, very rarely. Interfaces have been far more useful to me in my career, as far as major OO concepts go. If I'm extending, it's usually because someone brought in a new requirement after a products launch that requires very similar, but not quite the same, behavior as existing work. For example, we process data feed A already, and data feed B will be very similar. Rather than modifying the existing A processor, its often easier to lift out an abstract parent class and implement A and B as extensions of it. I almost never find myself extending concrete classes.
Inheritance is helpful when the domain is well-defined and the underlying problem is broadly similar enough to fill-in differences across what's being abstracted.
Some hand-picked examples of well-implemented inheritance in open source:
As a closing note, It works a lot better when the use of inheritance symbolically represents actual standards (SQL, HTTP, and/or standard libraries API's) that developers already are familiar with, rather than abstract concepts meaningful only to the writer.
I have used inheritance twice in the past two years. Here is the most recent example. The code is from an iOS application written in Swift. The task was to write a quiz application. I used a combination of a protocol and a base class to avoid duplicating the code to advance to the next question. All view controllers implement the Scorable protocol and the view controllers for individual questions all inherit from ScorableViewController.
// Scorable.swift
import Foundation
protocol Scorable {
var totalScore : Int {get set}
}
// ScorableViewController.swift
import UIKit
class ScorableViewController: UIViewController, Scorable {
//overrides here...
//This class exists to share the following code.
var totalScore : Int = 0
var currentChoice : Selection? = nil
final var choseOption : Bool {
get {
return currentChoice != nil
}
}
final override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
precondition(choseOption, "must choose option before proceeding")
precondition(segue.identifier != nil, "identifier is nil")
precondition(!segue.identifier!.isEmpty, "identifier is empty")
var dest = segue.destination as! Scorable
dest.totalScore = Selection.add(score: totalScore, selection: currentChoice!)
}
}
I use inheritance only if the model satisfies the Liskov Substitution Principle and if the language has strong OO primitives. Functional languages accomplish similar goals with different abstractions, e.g., type polymorphism, pattern matching, functional composition.
As an example, working in the payments business, we often model credit cards and bank accounts as different subclasses (or types) of a common superclass, given that these objects share a lot of semantics, i.e., they both send and receive payments.
Constantly. My company uses a popular framework that supports complex behavior defined largely in a declarative manner using inheritance; with method overrides for customizing business logic.
I also frequently use multiple inheritance and what are called "mix-in" classes in python to make more complex customizations reusable.
Yes. Mixins are a particularly handy and slightly less dangerous form of multiple inheritance than multiple inheritance from two fully-fledged and usable classes (which IME causes more problems than it solves). I didn't intend to imply they weren't multiple inheritance. Would it have been clearer to have said "with" instead of "and"?
You use inheritance when a library provides an interface that you want to use. Other than that, you're probably better off not using it. Certainly not in the idiot Programming 101 "lets design a restaurant" OOP way.
In iOS development, all the time. I subclassed UI components like UITextView and other things so I could customize its appearance and add functionality.
Inheritance is a great way to allow your newly defined class to interface with the language syntax or system environment features in a useful way. Doing something like inheriting from a dictionary in Python allows for you to extend a very versatile tool that already exists, that has been optimized for use in the language.
If you are going to bother inheriting from a class, then you should weigh the cost of your code complexity against it. It is definitely worth it sometimes
If you wrote both the class and sub-class, then you're likely over engineering the problem (unless you have a sufficiently large program you're working on)
In my web development career (with python) it is usually only simple mixin-like inheritance, mostly because I can't stand code redundancy.
In game development though, it is way easier to develop a full fledged class hierarchy. I think it is because OOP is supposed to model a physical world of objects, which is generally what you'll be simulating in games too.
19 comments
[ 3.4 ms ] story [ 49.7 ms ] threadIMHO OOP is a trap.
Some hand-picked examples of well-implemented inheritance in open source:
An example of where inheritance makes great sense is Django CBV (Class-based views), https://docs.djangoproject.com/en/1.11/topics/class-based-vi..., as well as Django REST Framework class views (http://www.django-rest-framework.org/api-guide/views/)
An example of where inheritance in the form of runtime metaprogramming makes sense is SQLAlchemy declarative and Django ORM.
An example where inheritance in the form of mixins make sense would be Django ORM, such as TimeStampedModel in django-extensions https://github.com/django-extensions/django-extensions/blob/....
An example where classes make sense in standard libraries would be (impure) interfaces such as csv.Dialect (https://github.com/python/cpython/blob/6aee6fb/Lib/csv.py#L2...)
An example of where inherited classes make sense in abstraction would be types (https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalch...) and dialects in SQLAlchemy (https://github.com/zzzeek/sqlalchemy/tree/master/lib/sqlalch...)
As a closing note, It works a lot better when the use of inheritance symbolically represents actual standards (SQL, HTTP, and/or standard libraries API's) that developers already are familiar with, rather than abstract concepts meaningful only to the writer.
// Scorable.swift
import Foundation
// ScorableViewController.swiftimport UIKit
class ScorableViewController: UIViewController, Scorable {
I also frequently use multiple inheritance and what are called "mix-in" classes in python to make more complex customizations reusable.
If you are going to bother inheriting from a class, then you should weigh the cost of your code complexity against it. It is definitely worth it sometimes
If you wrote both the class and sub-class, then you're likely over engineering the problem (unless you have a sufficiently large program you're working on)
In game development though, it is way easier to develop a full fledged class hierarchy. I think it is because OOP is supposed to model a physical world of objects, which is generally what you'll be simulating in games too.