edusolum

📖 Unit 3: Class Creation

# UNIT 3: CLASS CREATION

# 1. INTRODUCTION

In the world of software engineering, we are often tasked with representing complex real-world systems—like a banking network, a social media platform, or a physics engine—within the rigid confines of computer code. To bridge this gap, Java utilizes Object-Oriented Programming (OOP). While previous units focused on using pre-existing classes (like String or Scanner), Unit 3: Class Creation is where you transition from being a consumer of code to an architect of code.

Imagine you are designing a video game. Instead of managing thousands of individual variables for every player’s health, position, and inventory, you can create a single blueprint: the Player class. This blueprint defines what every player has (attributes) and what every player does (behaviors). This process of "bundling" data and behavior is the cornerstone of professional software development.

In this chapter, we will explore the philosophical underpinnings of Abstraction, the protective walls of Encapsulation, and the technical mechanics of Constructors, Methods, and Scope. By the end of this unit, you will be able to design robust, reliable, and reusable software components that adhere to the rigorous standards of the AP Computer Science A curriculum.


# 2. ALL KEY CONCEPTS, TERMS, AND PRINCIPLES

# Foundational Terms

  • Class: A formal blueprint or template used to create objects. It defines the variables and methods that the objects will possess.
  • Object: A specific instance of a class. If Car is the class, "My 2022 Blue Sedan" is the object.
  • Abstraction: The process of reducing complexity by hiding unnecessary details and showing only the essential features of an object.
  • Encapsulation: A mechanism of wrapping data (variables) and code (methods) together as a single unit and restricting direct access to some of the object's components.
  • Instance Variable: A variable defined in a class for which each instantiated object of the class has its own separate copy.
  • Constructor: A special method used to initialize objects. It sets the initial state of the object.
  • Access Modifier: Keywords (public, private) that set the visibility and accessibility of classes, variables, and methods.

# Technical Principles

  • Procedural Abstraction: Knowing what a method does without needing to know how it is implemented.
  • Data Abstraction: Naming data groups (like a class) without exposing how that data is stored mathematically or physically.
  • Pass-by-Value: The mechanism Java uses to pass arguments to methods. For primitives, a copy of the value is passed. For objects, a copy of the reference (memory address) is passed.
  • Static (Class) Variables/Methods: Members that belong to the class itself rather than any specific object instance.
  • Scope: The region of a program where a variable is accessible.
  • Shadowing: Occurs when a local variable has the same name as an instance variable, making the instance variable inaccessible by its simple name within that scope.
  • The this Keyword: A reference to the current object whose method or constructor is being called.

# 3. IN-DEPTH EXPLANATION

# 3.1 Abstraction and Program Design

Abstraction allows programmers to manage complexity.

  1. Data Abstraction: Instead of managing three separate integers for $x$, $y$, and $z$ coordinates, we create a Point class. We interact with the Point object rather than the raw integers.
  2. Procedural Abstraction: When you call Math.sqrt(16.0), you do not care if the computer uses the Babylonian method or Newton's method. You only care that it returns $4.0$.

Design Process: Before writing a single line of code, developers use "Natural Language" or UML (Unified Modeling Language) to plan.

  • Attributes (Has-a): What data does this object need? (e.g., A BankCard has a balance).
  • Behaviors (Does): What actions can it perform? (e.g., A BankCard can withdraw).

# 3.2 Impact of Program Design

Software does not exist in a vacuum.

  • Reliability: A reliable program handles "edge cases" (e.g., trying to withdraw more money than is in an account). We use thorough testing to ensure the state of an object remains valid.
  • Legal and Ethical Concerns:
    • Open Source: Code that is free to use and modify under specific licenses.
    • Proprietary/Copyright: Code that requires explicit permission or payment.
  • Social Impact: Decisions in class design (like how user data is stored) can lead to unintended privacy consequences.

# 3.3 Anatomy of a Class

A standard class in this course follows a specific structure:

Component Visibility Purpose
Class Header public Defines the name of the blueprint.
Instance Variables private Stores the state/data (Encapsulation).
Constructors public Initializes the private variables.
Methods public / private Defines the logic and behaviors.

Encapsulation is achieved by making variables private. This prevents external classes from "corrupting" the data. For example, if age is private, we can prevent a user from setting age = -500 by using a method that checks for validity.

# 3.4 Constructors

Constructors are called using the new keyword.

  • Signature: Consists of the name (which must match the class name) and the parameter list.
  • Default Constructor: If you write no constructors, Java provides one:
    • int $\rightarrow 0$
    • double $\rightarrow 0.0$
    • boolean $\rightarrow false$
    • Reference types $\rightarrow null$

The "Mutable Object" Trap: If a constructor takes an object (like a Date) as a parameter, storing that exact reference allows the caller to change the object outside the class. To maintain encapsulation, we should store a copy of the object.

# 3.5 Methods (Writing and Primitives)

Methods represent behaviors.

  • Accessor (Getter): A non-void method that returns the value of an instance variable.
  • Mutator (Setter): A method (usually void) that changes the value of an instance variable.
  • Return Statements: Once a return is executed, the method terminates immediately. Any code below it in that logic path is unreachable.

Pass-by-Value (Primitives):
If we have a method increment(int n) and we call increment(x), a copy of the value of $x$ is made. The original $x$ remains unchanged.

# 3.6 Methods (Passing and Returning Object References)

When an object is passed, the reference (the address in memory) is copied.

  • Aliasing: Two references pointing to the same object.
  • Side Effects: Because the method has a copy of the address, it can go to that address and change the object’s internal data.

# 3.7 Class Variables and Methods (static)

The keyword static means "belongs to the class."

  • Static Variables: Shared by every object of that class. If one object changes a static variable, it changes for all. Useful for constants (using final) or counters.
  • Static Methods: Can be called without creating an object (e.g., Math.abs()).
    • Constraint: Static methods cannot access instance variables or this because they don't belong to a specific instance.

# 3.8 Scope and Access

  1. Instance Level: Variables declared at the top of the class. Visible to all non-static methods.
  2. Local Level: Variables declared inside a method or block. They "die" when the block ends.
  3. Shadowing:
private int x;
public void setX(int x) {
    // The parameter 'x' shadows the instance variable 'x'.
    // To reach the instance variable, we need 'this.x'.
}

# 3.9 The `this` Keyword

this is a reference to the current object.

  • Used to distinguish instance variables from local variables.
  • Used to pass the current object as a parameter to another method.
  • Note: this cannot be used in static contexts.

# 4. EXAMPLES

# Example 1: Procedural Abstraction

When we use System.out.println(5 + 10);, we do not know how Java converts the integer $15$ into pixel patterns on a screen. We only care that the behavior is consistent. This is procedural abstraction.

# Example 2: Data Abstraction (The Rectangle)

Instead of tracking $x_1, y_1, x_2, y_2$ separately, we design:
$$Area = |x_2 - x_1| \times |y_2 - y_1|$$
By creating a Rectangle class, we abstract these four coordinates into one "shape" concept.

# Example 3: Designing a "Student" Class

  • Attributes: String name, int id, double gpa.
  • Behaviors: updateGPA(), getName().
    This design phase happens in English/Diagrams before coding.

# Example 4: Encapsulation in a BankAccount

public class BankAccount {
    private double balance; // Private protects the money

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }
}

If balance were public, someone could write account.balance = -1000000;.

# Example 5: Default Values Calculation

If a class Gadget has private int serial; private boolean isActive;, and we call new Gadget(), the state is:
$$serial = 0, isActive = false$$

# Example 6: The `new` Keyword and Reference

Gadget g = new Gadget();

  1. new allocates memory.
  2. Constructor initializes memory.
  3. The address (e.g., 0x7A1) is stored in g.

# Example 7: Constructor Overloading

A Circle class might have:

  1. public Circle() (sets radius to 1.0)
  2. public Circle(double r) (sets radius to r)

# Example 8: Pass-by-Value (Primitive)

public void addFive(int n) { n = n + 5; }
// Calling:
int x = 10;
addFive(x);
// Result: x is still 10.

$x_{original} = 10 \rightarrow n_{copy} = 10 \rightarrow n_{copy} = 15$. The original is untouched.

# Example 9: Pass-by-Value (Reference/Object)

public void reset(Point p) { p.setX(0); }
// Calling:
Point myPt = new Point(5, 5);
reset(myPt);
// Result: myPt now has X = 0.

Both myPt and p hold the same memory address.

# Example 10: Returning a Reference

public Point getLocation() {
    return this.location; 
}

If location is a mutable object, the caller can now change the object's internal state. This is a common security/reliability risk.

# Example 11: Static Variable for Counting

public class Robot {
    private static int totalRobots = 0;
    public Robot() {
        totalRobots++;
    }
}

Every time new Robot() is called, the same variable totalRobots increments.

# Example 12: Static Constants

public static final double PI = 3.14159;

  • static: Only one copy exists.
  • final: The value cannot be changed after initialization.

# Example 13: Static Method (Math Style)

public static double calculateInterest(double principal, double rate) {
    return principal * rate;
}

Called as Bank.calculateInterest(100, 0.05). No object needed.

# Example 14: Shadowing with `this`

public class Hero {
    private int health;
    public Hero(int health) {
        this.health = health; // this.health is the instance var, health is the param
    }
}

# Example 15: Scope - Local Variable Conflict

public void doWork() {
    int x = 5;
    if (true) {
        int x = 10; // ERROR: x is already defined in this method scope.
    }
}

A student uses the "Apache Commons" library for complex math. Since it is open source, they can include it if they follow the license. Using a paid library without paying is a violation of legal standards.

# Example 17: Mutator with Validation

public void setScore(int s) {
    if (s >= 0 && s <= 100) {
        score = s;
    }
}

Ensures $0 \le score \le 100$.

# Example 18: Accessor Method

public String getName() {
    return name;
}

Provides "read-only" access to a private variable.

# Example 19: Return Path Logic

public int checkSign(int n) {
    if (n > 0) return 1;
    if (n < 0) return -1;
    return 0; 
    System.out.println("Done"); // UNREACHABLE CODE ERROR
}

# Example 20: The `null` Reference

Student s;
The variable s exists in the stack but points to null. Attempting s.getName() results in a NullPointerException.

# Example 21: Deep Copy in Constructor (Advanced Design)

public Team(Coach c) {
    // Instead of this.myCoach = c;
    this.myCoach = new Coach(c.getName()); // Create a new object to avoid aliasing
}

# Example 22: Primitive Math in Methods

A method to calculate the hypotenuse:
$$c = \sqrt{a^2 + b^2}$$

public double getHypotenuse(double a, double b) {
    return Math.sqrt(a*a + b*b);
}

# Example 23: Multiple Parameters

Methods can take multiple types:
public void updateLog(String msg, int severity, double timestamp)
The order of arguments must match the signature exactly.

# Example 24: Method Decomposition

Instead of one giant processOrder() method, we break it down:

  1. validatePayment()
  2. checkInventory()
  3. generateReceipt()
    This promotes code reuse and clarity.

# Example 25: Societal Impact (Biased Algorithms)

If a CreditScore class design uses zipCode as an attribute, it might unintentionally reinforce socioeconomic biases. Programmers must consider these impacts during the design phase.

# Example 26: Reference Assignment (Aliasing)

Car car1 = new Car("Red");
Car car2 = car1;
car2.setColor("Blue");
// car1 is now Blue because they point to the same memory.

# Example 27: Final Instance Variables

private final int ID_NUMBER;
Must be initialized in the constructor and can never be changed again for that object.

# Example 28: This as a Method Argument

public void process() {
    DataAnalyzer.analyze(this); // Passes the entire current object to another class
}

# Example 29: Impact of System Reliability

A flight control system class must have $100%$ reliability. Developers use unit tests to verify that Altitude objects never have a negative value attribute.

# Example 30: Class vs Local Variable Names

public class Logic {
    private int val = 20;
    public void printVal() {
        int val = 50;
        System.out.println(val); // Prints 50
        System.out.println(this.val); // Prints 20
    }
}

# Example 31: Default Constructor Override

If you define public MyClass(int x) {}, Java removes the automatic no-argument constructor. Calling new MyClass() will now cause a compile error.

# Example 32: Object State Modification

public void birthday(Person p) {
    p.setAge(p.getAge() + 1);
}

Even though the reference is passed by value, the object's internal state is permanently modified.

# Example 33: Void Method Usage

Void methods are used for their "side effects" (changing instance variables or printing), not for returning data.

# Example 34: Class-Level Scope

Instance variables are declared outside of all methods. Their scope is the entire class.

# Example 35: Mathematical Expression in Return

public double getCircleArea(double r) {
    return Math.PI * Math.pow(r, 2); 
}

The expression is evaluated first, then the single resulting value is returned.

Certificate terms & implications

Course Mastery Certificates require an active Unlimited subscription at the time of generation and 100% course completion. They recognise learning content completion only — not an accredited qualification, licence, or professional credential unless explicitly stated. edusolum may modify eligibility, design, and issuance requirements per its Terms of Service.