In what ways are subtypes different from subclasses in usage?
Asked Answered
H

6

23

A subtype is established when a class is linked by means of extending or implementing. Subtypes are also used for generics.

How can I differentiate subtyping from subclasses?

Hoag answered 16/8, 2011 at 0:20 Comment(1)
#468645, might be helpful for you to understand what you are trying to understand.Intimate
I
17

In Java, subclassing is a kind of subtyping.

There are a number of ways Java allows subtyping:

  1. When class A extends B, A is a subtype of B because B b = new A(...); is ok.
  2. When interface A extends B, A is a subtype of B because B b = new A() { ... } is ok.
  3. When class A extends B, A[] is a subtype of B[] because B[] b = new A[0] is ok.
  4. When class A implements B, A is a subtype of B because B b = new A(...) is ok.

It sounds like you want a way to distinguish one from the others. The below should do that.

static boolean isSubclass(Class<?> a, Class<?> b) {
  return !b.isArray() && !b.isInterface() && b.isAssignableFrom(a);
}

It won't handle subtyping of generic classes due to type erasure though. Class instances don't carry type parameters at runtime so there is no way to distinguish the runtime type of a new ArrayList<String>() from a new ArrayList<Integer>().

Industrial answered 16/8, 2011 at 0:29 Comment(14)
Subclassing is not a kind of subtyping. The fact that some languages interrelate both concepts does not mean they are interrelated in general. Behaviour subtyping teaches us that mere subclassing is not enough - my Car can inherit from my ToyCar, but it will not be its true subtype.Dibbrun
@JohnV Sure. Is this related to Liskov substitution violations? E.g. a Guava ImmutableList<T> is not substitutable for a java.util.List<T> because ImmutableList doesn't support add.Industrial
What I meant - it should be clear that subtyping and subclassing are two orthogonal concepts. I can have one without the other (while not in all languages, unfortuantely).Dibbrun
@JohnV could add an answer that explains how? My naive understanding is that each type corresponds to a union of equivalence classes over values, and a subtype of T is just a subset of T that is itself a type. In Java, some values are primitive, some are arrays, and some are class instances. Each Java class, (except Object which is a supertype for array types) corresponds to a type that includes its instances and null. In that case, subclass relationships line up with subtypes. If I've gotten that horribly wrong, maybe write up an answer explaining how.Industrial
There are already answers for this question here mentioning that. Mind you, Java and C# do consolidate both concepts.Dibbrun
E.g. here the answer from Robert Harvey explains far better than I could: softwareengineering.stackexchange.com/questions/362316/…Dibbrun
@JohnV Thanks for the pointer. I'm still not sure where a subclass relationship is not a subtype relationship without a Liskov substitution violation that is arguably a programmer error.Industrial
try this, it helped me: cs.mcgill.ca/~jmerce1/cs302/notes/java.pdf Quote from there: Inheritance (= subclassing) induces subtyping in Java. But it is important to understand that they are not the sameDibbrun
@JohnV I never said they are the same. I said that subclassing is a kind of subtyping, which seems consistent with what B. Pientka says about AOP. The rest of that article seems to be more of "Liskov substitution violations aren't preventable without contracts" but that doesn't invalidate subclasses as subtypes. It just goes back to Harvey's point that type is related to "safe use", and in OO langs safety is mostly related to what messages a value can respond to. Which PL provides subclassing without a subclass relationship being a subtype relationship?Industrial
What about here, and the example of Deque?cmi.ac.in/~madhavan/courses/pl2009/lecturenotes/lecture-notes/… Also subtyping does not need to be achieved via inheritance, so that is why saying that it is "a kind of" sounds inaccurate to me.Dibbrun
Also, if I remember correctly, C++ lets you inherit privately, which effectively means just subclassing, not subtyping. With interfaces it is the other way around.Dibbrun
Fair enough. What would you suggest as an edit? This question has java, so I could prefix with "For the purposes of Java," and add a pointer to those lecture notes more generally.Industrial
I think if you just remove the first line, or add something like in "In Java, subclassing...." then it is entirely correct :)Dibbrun
@JohnV, Done. Thanks for taking the time to dig up all those cites.Industrial
L
11

For once, Wikipedia gives a very straight answer to the question:

http://en.wikipedia.org/wiki/Subtype_polymorphism

Subtyping should not be confused with the notion of (class or object) inheritance from object-oriented languages; subtyping is a relation between types (interfaces in object-oriented parlance) whereas inheritance is a relation between implementations stemming from a language feature that allows new objects to be created from existing ones. In a number of object-oriented languages, subtyping is called interface inheritance.

In short, subtyping occurs when you derive an interface (method signatures/access points/ways of reacting to the outside world) from another whereas subclassing occurs when you derive an implementation (methods, attributes/internal state and inside logic) of a class from another class through inheritance.

This terminology is not often used in this way and type usually refers to the data type.

Luminescent answered 16/8, 2011 at 0:30 Comment(0)
M
10

In general, subclassing means to inherit the attributes of a parent. Subtyping merely means that operations on the supertype can be performed on the subtype. Note that subclassing is a special case of subtyping.

in Java, interfaces represent the structure for describing what behaviors a type can exhibit, which makes it the natural representation for subtyping. Subclassing is manifested in the class hierarchy.

Mobility answered 16/8, 2011 at 0:32 Comment(0)
H
8

Subclass is not the same as subtype. You might create subclasses that are not subtypes. To understand what a subtype is, lets start giving an explanation of what a type is.

When we say that the number 5 is of type integer, we are stating that 5 belongs to a set of possible values (as an example, see the possible values for the Java primitive types). We are also stating that there is a valid set of methods I can perform on the value like addition and subtraction. And finally we are stating that there are a set of properties that are always satisfied, for example, if I add the values 3 and 5, I will get 8 as a result.

To give another example, think about the abstract data types, Set of integers and List of integers, the values they can hold are restricted to integers. They both support a set of methods, like add(newValue) and size(). And they both have different properties (class invariant), Sets does not allow duplicates while List does allow duplicates (of course there are other properties that they both satisfy).

Subtype is also a type, which has a relation to another type, called parent type (or supertype). The subtype must satisfy the features (values, methods and properties) of the parent type. The relation means that in any context where the supertype is expected, it can be substitutable by a subtype, without affecting the behaviour of the execution. Let’s go to see some code to exemplify what I’m saying. Suppose I write a List of integers (in some sort of pseudo language):

class List {
  data = new Array();

  Integer size() {
    return data.length;
  }

  add(Integer anInteger) {
    data[data.length] = anInteger;
  }
}

Then, I write the Set of integers as a subclass of the List of integers:

class Set, inheriting from: List {
  add(Integer anInteger) {
    if (data.notContains(anInteger)) {
      super.add(anInteger);
    }
  }
}

Our Set of integers class is a subclass of List of Integers, but is not a subtype, due to it is not satisfying all the features of the List class. The values, and the signature of the methods are satisfied but the properties are not. The behaviour of the add(Integer) method has been clearly changed, not preserving the properties of the parent type. Think from the point of view of the client of your classes. They might receive a Set of integers where a List of integers is expected. The client might want to add a value and get that value added to the List even if that value already exist in the List. But her wont get that behaviour if the value exists. A big suprise for her!

This is a classic example of an improper use of inheritance. Use composition in this case.

(a fragment from: use inheritance properly).

Hernia answered 8/8, 2013 at 15:57 Comment(4)
I know this is old but in your example isn't Set both a subclass of List but also a kind of sub type of List, that is I can pass it into a function which expects List. It would have been good to have seen your representation of a subtype in code.Selfregard
You can pass an instance of Set where a List is expected, but it won't behaves like a List, that is why is not a subtypeHernia
But if you did not override that add method then it would be. If you have an abstract class Fruit and Apple extends it, is Apple not a 'type' of fruit? Equally if you then extend Apple with Cox, is Cox not a 'type' of Apple and a 'type of fruit? The interface contract for any methods is the same.Selfregard
The whole thing about this is if you override a method from the parent class... if you don't override any method, that is a subtype in addition to a subclass. Preconditions and postconditions play the important role and that is more than the interface signature. I would suggest you to read the Liskov Substitution Principle, which is just what I had tried to describe in my answer.Hernia
E
1

In java, subtyping applies to interfaces, but subclasses does not apply to interfaces.

Exclosure answered 16/8, 2011 at 0:25 Comment(1)
subtyping applies to classes too however sublcass is strictly for classes.Independency
B
-5

I don't think Java distinguishes between them? You have only classes.

Break answered 16/8, 2011 at 0:22 Comment(4)
@JVerstry: I forgot about those, actually - but the question suggests that types are related to /classes/, and you can't create an interface off a class. I believe the OP has a non-java definition of those terms...Break
It depends on how you view things :) . A class can be seen as sealed box with an interface stuck onto it (like in UML diagrams). With this point of view, you can consider that extending a class effectively gives the subclass the same interface. Definining an interface in Java is simply a way to separate the method signatures from the class implementation.Luminescent
@James: The question was tagged 'java', so I put on my Java-framed glasses.Break
I've got my Java-framed glasses on too ;) . I've just gotten into a habit of seeing things from a bigger picture after reading some of Jon Skeet's replies. His knowledge of C is a definite plus for understanding programming languages in general.Luminescent

© 2022 - 2024 — McMap. All rights reserved.