week 11 (2)
Chapter 5. Object-Oriented Design
Inheritance
Inheritance allows a class to inherit properties and behaviors (methods) from another class, facilitating code reuse and polymorphism.
Syntax and Semantics of Inheritance: The subclass always mentions the superclass, creating a hierarchical relationship.
The text of the subclass must refer to the superclass, but the superclass's text does not need to mention its subclasses.
Open-Closed Principle: A class should not be designed to know about its heirs or subclasses; it should be open for extension but closed for modification.
Class Assertions: Involves method preconditions/postconditions and class invariants that ensure the integrity of the inherited properties.
The subclass may possess its own unique properties while preserving properties of its parent class.
Method Overriding
Method overriding in object-oriented programming allows a subclass to provide a specific implementation of a method that is already defined in its superclass.
Pre/Postconditions: Each method has conditions that must be fulfilled before (precondition) and after (postcondition) the method is executed.
Example: Method
mwith precondition (A) {x > 5} and postcondition {Q} can be overridden by another method (B) with stricter precondition {x > 10} which violates expectations if clients rely on the original contract.
Design By Contract vs Subcontracting
Introduction of the concept where a method's pre/postconditions are seen as a contract that must be fulfilled.
The idea behind subcontracting in inheritance is that when a subclass overrides a method, it must fulfill the original method's contract or provide improved behavior.
How Inheritance Can Be Dangerous: Overriding methods incorrectly can lead to violations of expected behavior, particularly if concurrent clients rely on the original method's guarantees.
Variance and Contra-variance
Variance refers to the way that argument and return types relate to each other in inheritance.
Covariance: A subclass can override a method and return a subtype while maintaining compatibility with the original superclass return type.
Example: A method returning
Animalcan be overridden in a subclass to returnDog.
Contravariance: Allows for overriding methods where a parameter's type can change to a more general type.
In Java and C++, covariance is supported, but contravariance is not.
Module View vs Type View
Module View: To describe the subclass as an extension; focuses on how it expands functionality.
Type View: More focused on the is-a relationship; indicates that a subclass is a type of superclass.
Example: A
Squarecan be viewed as aRectangle, but in terms of implementation, aRectanglemight refer to aSquareif not properly structured, leading to design issues.
Case Study: Java Stack
A class
Stack<E>is extendingVector<E>, introducing methods that don't respect the LIFO (Last In First Out) order expected of a stack.Problems arise due to the mix of the stack operations and those inherited from
Vector, such as adding/removing elements from arbitrary positions.Recommendation: Favor composition over inheritance. Instead of extending
Vector, encapsulate it within theStackclass.
Overriding and Class Assertions
Important to enforce preconditions and postconditions for methods in subclasses to ensure contract fulfillment.
Class assertions can help maintain clarity and consistency across branches of inheritance while preventing dangerous overrides.
Example of Invalid Overriding: A subclass overrides a superclass method intending to weaken the precondition or strengthen the postcondition incorrectly, causing runtime errors.
Security Vulnerabilities Related to Inheritance
Inheritance can introduce security vulnerabilities if not managed correctly.
Malicious overriding during the cloning process, for example, can result in security breaches where unauthorized code is executed.
Concept of how the
clone()method potentially allows subclass behavior to alter the expected integrity of the objects involved.
Proper encapsulation and design practices can help mitigate risks of inheritance misuse.
Hashing and Equality Contracts
Discusses the contract requirements for
hashCodeandequalsin Java to maintain expected behaviors across custom implementations.Always override
hashCode()alongsideequals()to ensure the integrity of collections likeHashMapwhere objects are used as keys.General Contract of
hashCode: Equal objects should have the same hash code; the contract must maintain consistency and reflect the equivalence relationship defined inequals.Example of how to effectively implement these methods in classes and implications in the security context of software design.
Recommendations for Design Improvements
Favor composition (aggregating components) over inheritance to provide better control and avoid convoluted hierarchies.
Example: Replace direct inheritance of properties in classes with composition to maintain a clear contract and avoid issues that stem from unintended behaviors.
Conclusion
The design of classes through inheritance must be handled with caution, applying principles such as encapsulation, clear contract adherence, and an awareness of potential security vulnerabilities.
A deep understanding of method overriding, class assertions, and contract design is essential for maintaining integrity and avoid misuses of inheritance in software design.