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 m with 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 Animal can be overridden in a subclass to return Dog.

  • 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 Square can be viewed as a Rectangle, but in terms of implementation, a Rectangle might refer to a Square if not properly structured, leading to design issues.

Case Study: Java Stack

  • A class Stack<E> is extending Vector<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 the Stack class.

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 hashCode and equals in Java to maintain expected behaviors across custom implementations.

  • Always override hashCode() alongside equals() to ensure the integrity of collections like HashMap where 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 in equals.

    • 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.