Back to Explore

Week #6 — Relationships, Abstraction, and Interfaces (CST8284) — Comprehensive Study Notes Summary & Study Notes

These study notes provide a concise summary of Week #6 — Relationships, Abstraction, and Interfaces (CST8284) — Comprehensive Study Notes, covering key concepts, definitions, and examples to help you review quickly and study effectively.

1.6k words3 views
Notes

📝 Source summary / Task overview

Purpose: Capture and summarize the materials from the provided lecture files. These notes organize and explain the key Java object-oriented topics covered: relationships (association, aggregation, composition), inheritance, abstraction, abstract classes/methods, and access control.

Scope: The rest of these notes extract and condense the lecture content into clear bite-sized sections so you can review definitions, rules, examples, and design guidance quickly.

How to use: Read the sections in order (relationships → inheritance/abstraction → access control → interfaces). Use the examples and rules as checklists when writing or reviewing Java code.

🔗 Relationships (Association, Aggregation, Composition)

Association: A general relationship describing activity between two classes. It is often shown as a straight line (optionally with an arrow to indicate direction). Association implies that objects communicate via links (references).

Aggregation: A has-a relationship where an aggregating object owns or manages a collection of other objects. The aggregated objects can usually exist independently of the aggregator. Typical examples: Professor has many Students, Hotel has many Suites, Truck has many Wheels. In implementation, aggregation is commonly represented as a data field in the aggregating class (e.g., a collection of Student objects in a Professor class).

Composition: A stronger form of aggregation: a strong has-a relationship where parts are dependent on the whole; the child cannot exist meaningfully without the parent. Examples: Room has-a Door, Car has-a Wheel (in contexts where the wheel cannot exist independently). Composition is modeled similarly (fields that are instantiated and managed by the parent), but the lifecycle dependency is stronger: destroying the parent typically destroys the children.

Aggregation vs Composition (summary): Aggregation = weak ownership; child can exist independently. Composition = strong ownership; child depends on parent. Both enable code reuse and structure object models with has-a relationships.

🧬 Inheritance (is-a relationship)

Inheritance: A subclass is a specialization of a superclass; it inherits characteristics (fields and methods) and can be treated as the parent type. Examples: Motorcycle is-a Vehicle, Car is-a Vehicle.

Key questions and rules to remember:

  • Not every class should or can be inherited; design carefully.
  • Java supports single class inheritance: a class cannot extend more than one class.
  • The keyword super refers to the superclass, and this is used for constructor chaining within the same class.
  • Subclasses can call superclass constructors using super(...); if a superclass has no default constructor, subclass constructors must explicitly call an appropriate super constructor.
  • Use final to prevent methods from being overridden.

⚙️ Overloading vs Overriding

Overloading: Same method name, different parameter signature (compile-time polymorphism). Constructors can be overloaded.

Overriding: Same method name and signature in a subclass (runtime polymorphism). Overriding happens with inherited instance methods (unless marked final). Constructors cannot be overridden (they are not inherited).

Timing: Overloading is resolved at compile time; overriding is resolved at runtime. The static keyword relates to compile-time elements (class-level), not instance-level overriding.

🧠 Abstract classes and Abstract methods

Abstract class: A class declared with the abstract keyword. It may contain both concrete (implemented) and abstract (unimplemented) methods. An abstract class cannot be instantiated directly; it’s intended as a superclass or template.

Abstract method: Declared with the abstract keyword and has no body (no curly braces); it ends with a semicolon. If a class contains any abstract method, the class itself must be declared abstract.

Purpose of abstract methods: To specify a behavior contract without implementation details, forcing concrete subclasses to provide their own implementations. This enforces a design contract and supports polymorphism (client code can use abstract types and rely on subclass implementations).

Rules & best practices:

  • A subclass must implement all inherited abstract methods to become concrete; otherwise the subclass stays abstract.
  • Abstract classes can have constructors (useful to initialize inherited state). Making these constructors protected is good practice because abstract classes are not meant to be instantiated directly.
  • Abstract classes can have instance variables and concrete methods; interfaces (pre-Java 8) could only have abstract methods and constants.
  • You can use abstract class names as reference types for polymorphic behavior: methods can accept abstract superclasses and operate on any concrete subclass instance.

Why define a method as abstract? When the general concept cannot sensibly provide an implementation (e.g., computing earnings for a generic Employee where different employee types calculate earnings differently), declare the method abstract so each concrete subclass implements its logic.

🔒 Access modifiers (visibility and inheritance)

Java access levels determine member visibility:

  • public: Visible everywhere (class, package, subclass, global). Public class members are inherited by subclasses.
  • protected: Visible inside the same package and to subclasses (even if subclasses are in different packages).
  • (package-private / no modifier): Visible only within the same package.
  • private: Visible only within the declaring class; not visible to subclasses and not inherited.

Constructors in abstract classes: Constructors can be public or protected, but using protected prevents misuse (attempting to construct abstract types) and still allows subclasses to call super(... ).

Summary matrix (quick):

  • Class: public — visible
  • Package: public/protected/none — varying visibility
  • Subclass: public/protected — visible
  • Global: only public

📚 Practical tips from Part A

  • Use abstract classes when you have shared state or implemented behavior to inherit, plus abstract methods to force specialization.
  • Use composition and aggregation for code reuse and to model real-world ownership; choose composition for strict lifecycle coupling.
  • Prefer protected constructors in abstract superclasses to allow subclass construction while discouraging instantiation of abstract types.

🧩 Java Interfaces — definition and core concepts

Interface: A type that declares a collection of abstract methods (and constants). Interfaces specify a contract: classes that implement the interface must provide implementations for every abstract method (unless the class is declared abstract).

Key facts:

  • Interfaces cannot be instantiated directly.
  • Methods declared in an interface are implicitly public (and abstract, pre-Java 8).
  • Fields are implicitly public static final (constants).
  • A class implements an interface with the implements keyword and must implement all methods or be declared abstract.
  • A class can implement multiple interfaces (Java supports multiple interface inheritance for types).

🛠 Example patterns and use cases

  • Use interfaces when unrelated classes need to share a common set of behaviors (e.g., Payable, Doable, Encryptable), enabling polymorphic processing.
  • Interfaces define what operations are possible, not how they are performed—this allows different classes to provide different implementations behind the same API.
  • UML: interfaces are marked with «interface» and a dashed realization arrow points from implementing class to the interface.

🔁 Multiple interfaces and polymorphism

  • A class can implement multiple interfaces: class MyClass implements Interface1, Interface2 { ... }
  • Interface types can be used as reference types: an interface variable can reference any object whose class implements that interface, enabling polymorphism via method calls on the interface type.
  • Programming to an interface (not an implementation) increases flexibility and loose coupling: code depends on behavior, not concrete classes.

🧾 Common Java API interfaces & examples

Comparable: Defines compareTo(...) for ordering objects. The method returns a negative, zero, or positive int to indicate ordering. Implementing Comparable allows objects to be sorted (e.g., Collections.sort).

Iterator: Provides methods hasNext(), next(), and remove() to iterate a collection of objects one at a time. Implementing Iterator enables safe traversal and supports the enhanced for-each loop in many contexts.

Other functional interfaces: Examples include Runnable, Comparator, ActionListener — interfaces with a single abstract method (SAM). These are especially relevant for lambda expressions and method references.

✨ Interface enhancements since Java 8

  • default methods: Interfaces can provide concrete method implementations using the default keyword. This allows evolving interfaces without breaking existing implementors.
  • static methods: Interfaces can contain static helper methods directly, avoiding separate utility classes.
  • functional interfaces: Interfaces that declare exactly one abstract method (SAM) are functional interfaces, enabling lambda expressions.

Design implication: With default and static methods, interfaces can now provide shared behavior while still allowing multiple inheritance of type. Use default methods judiciously to avoid ambiguity in multiple inheritance scenarios.

⚖️ Interface vs Abstract class (decision guidance)

  • Use an interface if you only need to declare method signatures (no default state) or when multiple, unrelated classes must implement the same behavior. Interfaces offer maximum flexibility since classes can implement many interfaces.
  • Use an abstract class when you want to provide partial implementation or share instance fields among closely related classes.
  • Remember: a class can extend one class and implement multiple interfaces.

🧭 Design trade-offs: implementation inheritance vs interface inheritance

Implementation inheritance (extends): Best for small sets of tightly coupled classes that share implementation details. Changes in a superclass affect all subclasses and increase coupling.

Interface inheritance (implements): Better for flexibility and loose coupling. Requires implementing methods in each class (more work), but allows independent evolution and interchangeability of implementations.

✅ Practical tips and best practices

  • Prefer programming to an interface when designing APIs and modules, to allow swapping implementations without changing clients.
  • When adding functionality to widely used interfaces, consider default methods to avoid breaking implementors.
  • Choose abstract classes when there is meaningful shared state or common method implementations you want to reuse.
  • Name interface methods in general, descriptive ways (e.g., getMeasure()) so many unrelated classes can implement them consistently.

🔍 Summary

Interfaces and abstract classes are tools for abstraction: interfaces define contracts; abstract classes provide a template with optional common state and behavior. Use interfaces for wide applicability and flexibility; use abstract classes when you need to share code or state among a family of related types. Combine these with appropriate relationships (association, aggregation, composition) and access control to model robust, maintainable Java systems.

Sign up to read the full notes

It's free — no credit card required

Already have an account?

Create your own study notes

Turn your PDFs, lectures, and materials into summarized notes with AI. Study smarter, not harder.

Get Started Free
Week #6 — Relationships, Abstraction, and Interfaces (CST8284) — Comprehensive Study Notes Study Notes | Cramberry