What is the difference between subtyping and inheritance in OO programming?
Asked Answered
D

6

37

I could not find the main difference. And I am very confused when we could use inheritance and when we can use subtyping. I found some definitions but they are not very clear.

What is the difference between subtyping and inheritance in object-oriented programming?

Deneendenegation answered 11/5, 2014 at 11:40 Comment(5)
Where have you seen them being described as being different?Nisa
@JonSkeet - Are all the answers here wrong? :/Miles
@Sipo: While not necessarily wrong as such, I think if the OP had included some context (4 years ago...) it would have made for a significantly better question.Nisa
@JonSkeet - So... Is there a difference? I came across this question just now...Miles
@Sipo: I think they're used slightly inconsistently between languages, to be honest.Nisa
R
50

In addition to the answers already given, here's a link to an article I think is relevant. Excerpts:

In the object-oriented framework, inheritance is usually presented as a feature that goes hand in hand with subtyping when one organizes abstract datatypes in a hierarchy of classes. However, the two are orthogonal ideas.

  • Subtyping refers to compatibility of interfaces. A type B is a subtype of A if every function that can be invoked on an object of type A can also be invoked on an object of type B.
  • Inheritance refers to reuse of implementations. A type B inherits from another type A if some functions for B are written in terms of functions of A.

However, subtyping and inheritance need not go hand in hand. Consider the data structure deque, a double-ended queue. A deque supports insertion and deletion at both ends, so it has four functions insert-front, delete-front, insert-rear and delete-rear. If we use just insert-rear and delete-front we get a normal queue. On the other hand, if we use just insert-front and delete-front, we get a stack. In other words, we can implement queues and stacks in terms of deques, so as datatypes, Stack and Queue inherit from Deque. On the other hand, neither Stack nor Queue are subtypes of Deque since they do not support all the functions provided by Deque. In fact, in this case, Deque is a subtype of both Stack and Queue!

I think that Java, C++, C# and their ilk have contributed to the confusion, as already noted, by the fact that they consolidate both ideas into a single class hierarchy. However, I think the example given above does justice to the ideas in a rather language-agnostic way. I'm sure others can give more examples.

Rovelli answered 28/3, 2016 at 16:32 Comment(1)
That was a perfectly picked excerpt. Thank you for sharing helped cleared my doubts.Abney
S
15

A relative unfortunately died and left you his bookstore.

You can now read all the books there, sell them, you can look at his accounts, his customer list, etc. This is inheritance - you have everything the relative had. Inheritance is a form of code reuse.

You can also re-open the book store yourself, taking on all of the relative's roles and responsibilities, even though you add some changes of your own - this is subtyping - you are now a bookstore owner, just like your relative used to be.

Subtyping is a key component of OOP - you have an object of one type but which fulfills the interface of another type, so it can be used anywhere the other object could have been used.

In the languages you listed in your question - C++, Java and C# - the two are (almost) always used together, and thus the only way to inherit from something is to subtype it and vice versa. But other languages don't necessarily fuse the two concepts.

Seagraves answered 11/5, 2014 at 11:56 Comment(0)
H
8

Inheritance is about gaining attributes (and/or functionality) of super types. For example:

class Base {
    //interface with included definitions

}

class Derived inherits Base {
    //Add some additional functionality.
    //Reuse Base without having to explicitly forward
    //the functions in Base
}

Here, a Derived cannot be used where a Base is expected, but is able to act similarly to a Base, while adding behaviour or changing some aspect of Bases behaviour. Typically, Base would be a small helper class that provides both an interface and an implementation for some commonly desired functionality.

Subtype-polymorphism is about implementing an interface, and so being able to substitute different implementations of that interface at run-time:

class Interface {
    //some abstract interface, no definitions included
}

class Implementation implements Interface {
    //provide all the operations 
    //required by the interface
}

Here, an Implementation can be used wherever an Interface is required, and different implementations can be substituted at run-time. The purpose is to allow code that uses Interface to be more widely useful.

Your confusion is justified. Java, C#, and C++ all conflate these two ideas into a single class hierarchy. However, the two concepts are not identical, and there do exist languages which separate the two.

Hector answered 11/5, 2014 at 11:49 Comment(2)
Can you list languages which separate the two ?Thorite
@letronje: Inheritance without subtyping is often implemented via a mixin concept (but a mixin is often slightly less restricted than inheritance). For example, in D, you can write template mixins, which are essentially a way to inject code and data into an arbitrary scope.Hector
A
5

If you inherit privately in C++, you get inheritance without subtyping. That is, given:

class Derived : Base        // note the missing public before Base

You cannot write:

Base * p = new Derived();   // type error

Because Derived is not a subtype of Base. You merely inherited the implementation, not the type.

Autonomy answered 11/5, 2014 at 11:46 Comment(2)
Technically, you still get subtyping with private inheritance, it's just that the subtyping is private to the class...Hector
If I change the inheritance to : class Derived : public Base can I write : Base * p = new Derived();Deneendenegation
B
1

Subtyping doesn't have to be implemented via inheritance. Some subtyping that is not inheritance:

  1. Ocaml's variant
  2. Rust's lifetime anotation
  3. Clean's uniqueness types
  4. Go's interface
Brasca answered 13/5, 2018 at 7:35 Comment(0)
I
1

in a simple word: subtyping and inheritance both are polymorphism, (inheritance is a dynamic polymorphism - overriding). Actually, inheritance is subclassing, it means in inheritance there is no warranty to ensure capability of the subclass with the superclass (make sure subclass do not discard superclass behavior), but subtyping(such as implementing an interface and ... ), ensure the class does not discard the expected behavior.

Implead answered 25/5, 2018 at 15:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.