Subtyping and Java - Part 2
Sanjoy Kumar Malik .
Senior Software Architect - Java Architect, Cloud Architect, AWS Architect?? All views are my own
This article is the continuation of the topic “Subtyping and Java” that we started in the previous article. To start with we will touch upon the concept of specification and implementation aspects of a class. We will limit our focus only within Java Classes.
A class’s specification is a detailed description of what it exactly does. In other words, a specification clearly describes all the features visible to the clients. And a class’s implementation focuses on the representations and mechanisms to achieve those features.
When we talk about type, we focus on the specification. Java interfaces hold the specifications, but they lack implementations.
Client code depends only on the specifications. Therefore, your classes or interfaces must be consistent with their specifications. If that happens, your class will be correct and the client code will be happy.
When writing the specifications, you should be clear about three things without ambiguity: preconditions, postconditions, and invariants. Preconditions and preconditions are related to methods declared inside Java classes and interfaces. And invariants are related to global properties applicable to all instances of a class. Every method implementation must respect the invariants.
We will understand the concepts of preconditions, postconditions, and invariants with an simple example. Consider the below class.
The precondition is something that must hold whenever a method is called. The postcondition is something that the method guarantees when it returns.
Consider the below client code:
The above client code will fail with an exception because the client code didn’t give respect to the method contract by violating the precondition. Client code needs to satisfy the precondition.
What about the below client code-snippet?
In this case, client will get expected result because client code satisfies the precondition. When client code satisfies the precondition, it is the service implementer’s responsibilities to satisfy the postcondition.
If you observe carefully the implementation of the class SpecialSubtractor, you will see that all the methods (here only subtract) of the class SpecialSubtractor preserve the invariant (aka class invariant) that state of the SpecialSubtractor object is never negative.
Always consider invariants when you are designing method contract (precondition and postcondition).
Now consider the below subclass of SpecialSubtractor.
Since any Java subclass is Java subtype, we can say that the subclass VerySpecialSubtractor is a subtype of the supertype SpecialSubtractor.
Now we will investigate if an object of VerySpecialSubtractor can be substituted where an object of SpecialSubtractor is expected.
From the above design, we can say that the invariant(s) of SpecialSubtractor is maintained in VerySpecialSubtractor. Moreover, there is no change in postcondition. But the subtype VerySpecialSubtractor has slightly changed the contract of subtract method of supertype SpecialSubtractor.
Supertype Precondition: Both operands are greater than zero and operand1 is greater than operand2 and operand1 must be greater than 5
Subtype Precondition: Both operands are greater than zero and operand1 is greater than operand2 and operand1 must be greater than 1
If you observe, you will see that the subtype precondition is weaker than the supertype precondition.
By ‘weaker,’ we mean that the subtype precondition is less strict than the supertype.
In subtype precondition, one expectation from client (operand1 must be greater than 5) is weakened (operand1 must be greater than 1). In this case, subtype method asks less from the client than the supertype method does. But subtype implementation needs to handle new inputs (2,3,4,5) that were previously excluded by the spec.
Consider the below client code based on supertype (SpecialSubtractor) specification.
The above client code will produce 3 as output.
Next we will replace the SpecialSubtractor object with an object of VerySpecialSubtractor type as shown below.
In this case, the client code will also produce 3 as output.
Important points…
From the above observations, we can say that Java subtype VerySpecialSubtractor has a stronger specification than SpecialSubtractor. Hence, we can consider subtype VerySpecialSubtractor as true subtype. Remember, Java subtype is not same as true subtype. As a software designer, your goal is to design Java subtypes that are true subtypes.
That’s all for this article!
Read the previous article >> https://www.dhirubhai.net/pulse/subtyping-java-sanjoy-kumar-malik-l1zhc/
References
https://courses.cs.washington.edu/courses/cse331/10au/lectures/subtypingexamples.pdf
https://web.mit.edu/6.031/www/sp19/classes/07-designing-specs/
https://www.cs.rpi.edu/academics/courses/spring21/csci2600/handout-files/files_29_03/SubtypePolymorphism.pdf
https://www.cs.mcgill.ca/~cs202/2011-01/lectures/maja/subtyping-and-inheritance-in-java.pdf
https://courses.cs.washington.edu/courses/cse331/16wi/L12/L12-Subtyping.pdf
https://cs.wellesley.edu/~cs251/f19/slides/oo-subtypes-4up.pdf
https://courses.cs.washington.edu/courses/cse331/10sp/lectures/lect06-subtyping.pdf
Computer Science | Senior IT Lab Engineer | Risk Champion | at Amity University Dubai
5 个月Discussion on subtyping and Java. It focuses on the distinction between class specifications and, implementations. Java interfaces define specifications, while classes provide implementations. Client code relies solely on specifications, so classes must be consistent with their contracts.
Technologist & Believer in Systems for People and People for Systems
5 个月Thanks for the simplified walkthrough for the good ??