UNC COMP 301 - F26/Lec 3 - Motivating OO; Encapsulation; Assn 01; Interfaces
Watch on YouTube →
Overview
Muhammad Sayeed Ghani develops a Java triangle-area application into an object-oriented design, using Triangle and Point abstractions to demonstrate instance methods, static constants, encapsulation, immutability, and avoiding redundant state. He then introduces Assignment 1 topics—Java reflection and constructor chaining—and explains how programming to interfaces lets client code use different Point implementations, such as Cartesian and polar coordinates, without depending on a concrete class.
Key takeaways
- A method is a good instance method when its behavior is centered on one object: Triangle area and category use the receiver's stored vertices, while a generic point-to-point distance can be an instance method on Point with one other Point parameter.
- Aliasing can corrupt related objects even when an operation appears local: two Triangles sharing Point references will both reflect changes to those mutable Points.
- Private fields do not by themselves eliminate aliasing; immutable Points and Triangles avoid shared-state mutations by returning new objects from move operations.
- Store only essential state when possible: an axis-aligned Square needs a top-left Point and side length, while area and other corners can be derived to avoid inconsistent duplicate fields.
- Programming to interfaces separates a variable's contract from its implementation, allowing a Triangle to combine CartesianPoint and PolarPoint instances through the same Point type.
- Java constructor chaining uses this(...) to reuse initialization logic, but the delegation call must be the constructor's first statement and there can be only one such call per constructor.
Chapters
- Muhammad Sayeed Ghani plans to complete the triangle-area application's transition from procedural code to object-oriented design.
- The lecture covers encapsulation, selected Assignment 1 details, and Java interfaces; lecture code is available on Canvas.
- An object's state is determined by its fields, and local variables or parameters take precedence over fields during name resolution.
- Triangle category and area depend on a particular triangle, so they fit as instance methods in the Triangle class.
- After moving those operations into Triangle, callers use the triangle object and provide no coordinate parameters because the object owns its vertex data.
- Point distance remains a static operation at this stage because a Triangle has three sides and the method needs two explicit points to identify the desired distance.
- Three pairs of Triangle coordinate fields can be represented more clearly as three Point objects, each with x and y data.
- Once Point exists, distance belongs naturally to that abstraction as an instance method such as distanceTo(otherPoint).
- The receiving Point supplies one endpoint, so the distance method needs only the other Point as a parameter.
- A named tolerance such as SIDE_EPSILON can handle small floating-point errors when comparing Triangle side lengths.
- Declare an unchanging class-wide constant with both static and final, initialize it at declaration, and use uppercase naming.
- The tolerance lets equality checks treat side lengths within a small difference as effectively equal rather than relying on exact double equality.
- Encapsulation protects an object's fields and controls which operations external code can access.
- Private fields prevent client code from changing representation directly and let a class switch internally—for example, from Cartesian to polar coordinates.
- An interface defines the public contract while allowing a class to change its internal representation and implementation without changing client code.
- Java access modifiers apply to fields and methods; private provides the strongest protection and public the least.
- Default access and protected both allow package access, but protected also allows access from subclasses in other packages.
- Because protected exposes members to a wider set of classes, default access is more restrictive than protected.
- The example creates two triangles that share Point objects P2 and P3, then shifts Triangle 1's vertex x-coordinates by 5.
- Triangle 1 keeps the same perimeter after translation, but Triangle 2's perimeter changes from about 63 to 70 because shared vertices moved.
- The unintended change is an aliasing bug: separate references point to the same mutable objects.
- A second example constructs separate Point objects for each triangle; shifting one triangle then leaves the other's perimeter unchanged.
- Making Point data private alone is insufficient if getters and setters still let clients mutate shared Point objects.
- Use immutable Point and Triangle objects so existing coordinates cannot be changed through another reference.
- A move operation can return a new Point or Triangle at the translated location instead of modifying the original object, similar to Java String behavior.
- Represent an axis-aligned Square with a top-left Point and one side length rather than storing all four corners, width, height, and area.
- If arbitrary rotation is allowed, the representation must also capture orientation; opposing corners or a position, side length, and angle can encode that information.
- Redundant fields can contradict one another—for example, a stored area can become inconsistent with a changed side length.
- A derived value such as area can be calculated on demand, though caching it may be worthwhile when calculation is expensive and frequent.
- A Square can derive its top-right corner from its top-left coordinates and side length instead of storing another Point.
- Java getter and setter names conventionally use getFieldName and setFieldName, with lower camel case for method names.
- Validate a side-length setter so nonpositive values are rejected; serious invalid input can trigger IllegalArgumentException with a diagnostic message.
- Java reflection can inspect class fields and methods, including private members, and can bypass ordinary encapsulation; Ghani warns against routine use.
- Reflection can be useful for testing, including unit tests that need to inspect implementation details.
- Overloaded constructors can delegate using this(...), such as a one-argument Player constructor supplying a default health value of 100.
- A this(...) constructor call must be the first statement, and one constructor cannot make two separate constructor calls.
- An interface declares method signatures—names, parameters, and return types—that implementing classes must expose publicly.
- A Java class can implement multiple interfaces, allowing it to satisfy several distinct contracts.
- One naming convention keeps the abstraction name for the interface and appends Impl to a concrete class, such as Point and PointImpl.
- The Point interface example requires implementations to provide four specified methods.
- Declare a variable as the interface type, such as List a = new ArrayList(), rather than tying client code to ArrayList.
- Likewise, use Point as a Triangle's vertex type and instantiate a concrete implementation such as CartesianPoint.
- A PolarPoint can implement getX and getY as derived values using radius times cosine or sine of the angle.
- With interface-typed vertices, one Triangle can accept both CartesianPoint and PolarPoint objects; concrete-class-typed vertices would reject a mixed implementation at compile time.
Summary, takeaways, and chapters were generated by AI from the video's transcript and may contain errors. The video belongs to its creator, Muhammad Sayeed Ghani.