Unit 5 - Writing Classes
Writing Classes
- Introduction
- Anatomy of a Class
- Constructors
- Accessor Methods
- Mutator Methods
- Writing Methods
- Static Variables and Methods
- Scope and Access
- This Keyword
- Hacks
Introduction
A class serves as a blueprint for creating objects in programming. It encapsulates data and methods that operate on that data. To define a class, specify its access level (public or private), use the class
keyword, and provide a name. Inside the class, you define variables to hold data and methods to perform operations. For instance, in the AreaCalculator
class, you can define instance variables and methods to calculate areas of various shapes, illustrating how classes structure and manage data and functionality.
Anatomy of a Class
A class is a blueprint for creating objects, containing variables and methods to manage data and perform actions. To define a class, specify its access level (public or private), use the class
keyword, and provide a name. Enclose the class contents within curly braces {}
. For example, the AreaCalculator
class can be defined as follows:
public class AreaCalculator {}
Inside the curly braces, you can declare instance variables to store data and methods to perform operations. For instance, an AreaCalculator
class might include an instance variable to track the number of shapes processed:
public class AreaCalculator {
private int numShapes;
}
The numShapes
variable is private to restrict access from other classes, ensuring it is only accessible within the AreaCalculator
class.
Constructors
Constructors are special methods used to initialize objects of a class. They have the same name as the class and no return type. Every class must have at least one constructor, and if none is provided, a default constructor is created. Constructors should be public so that objects can be instantiated from other classes.
For example, the AreaCalculator
class includes a constructor to initialize the numShapes
variable:
public class AreaCalculator {
private int numShapes;
public AreaCalculator() {
numShapes = 0;
}
}
Constructors can also take parameters to initialize instance variables with specific values. For example, the Car
class has a parameterized constructor:
public class Car {
private String brand;
private String model;
private int year;
public Car(String make, String carModel, int yearMade) {
brand = make;
model = carModel;
year = yearMade;
}
}
In this case, constructor parameters are used to set the initial values of brand
, model
, and year
.
Accessor Methods
Accessor methods, also known as getters, are used to retrieve the value of private instance variables from outside the class. They are public methods that return the value of a variable without modifying it.
For example, to access the numShapes
variable in the AreaCalculator
class, you can create an accessor method like this:
public class AreaCalculator {
private int numShapes;
// Accessor method for numShapes
public int getNumShapes() {
return numShapes;
}
}
Accessor methods typically have a return type matching the variable’s type and usually consist of a single line that returns the value of the variable.
Mutator Methods
Mutator methods, also known as setters, are used to modify the value of private instance variables. They are public methods that typically have a void
return type and accept parameters to update the variable.
For example, in the Car
class, a mutator method for the year
variable might look like this:
public class Car {
private int year;
// Mutator method for year
public void setYear(int newYear) {
year = newYear;
}
}
Mutator methods allow you to change the value of instance variables after an object has been created, providing a controlled way to modify data.
Writing Methods
Methods are used to perform actions and compute values within a class. They can take parameters and return values. For instance, in the AreaCalculator
class, you might write methods to calculate the area of different shapes. When writing methods, remember that primitive types are passed by value, meaning changes to parameters do not affect the original variables. Objects are passed by reference, so changes to an object’s attributes inside a method will affect the original object.
Here are examples of methods for calculating areas in the AreaCalculator
class:
public class AreaCalculator {
private int numShapes;
// Method to calculate the area of a triangle
public double triangleArea(double base, double height) {
double area = (base * height) / 2;
numShapes++;
return area;
}
// Method to calculate the area of a rectangle
public double rectangleArea(double length, double width) {
double area = length * width;
numShapes++;
return area;
}
// Method to calculate the area of a trapezoid
public double trapezoidArea(double base1, double base2, double height) {
double area = (base1 + base2) * height / 2;
numShapes++;
return area;
}
}
Each method performs a calculation and updates the numShapes
variable to reflect that a shape’s area has been calculated.
Static Variables and Methods
Static variables and methods belong to the class rather than to any specific object. They are shared across all instances of the class and can be accessed without creating an object. To define a static variable or method, use the static
keyword.
For example, in the AreaCalculator
class, you can make numShapes
and the area calculation methods static:
public class AreaCalculator {
private static int numShapes;
// Static method to calculate the area of a rectangle
public static double rectangleArea(double length, double width) {
double area = length * width;
numShapes++;
return area;
}
// Static method to calculate the area of a triangle
public static double triangleArea(double base, double height) {
double area = (base * height) / 2;
numShapes++;
return area;
}
// Static method to calculate the area of a trapezoid
public static double trapezoidArea(double base1, double base2, double height) {
double area = (base1 + base2) * height / 2;
numShapes++;
return area;
}
// Static method to get the number of shapes calculated
public static int getNumShapes() {
return numShapes;
}
}
Static methods and variables are accessed using the class name, like AreaCalculator.rectangleArea(5.0, 3.0)
, without needing to instantiate an AreaCalculator
object.
Scope and Access
Scope refers to the visibility and accessibility of variables, methods, and other elements within a program. In Java, there are two main types of scope:
-
Global Scope: Variables and methods with global scope are accessible from anywhere within the class. For example, instance variables defined outside of methods but inside the class have global scope within that class.
-
Local Scope: Variables with local scope are accessible only within the block of code in which they are defined, such as within a method. For example, variables declared inside a method exist only during the execution of that method and are not accessible outside of it.
In the AreaCalculator
class, the numShapes
variable has global scope within the class, while the area
variable used in methods like triangleArea
has local scope:
public class AreaCalculator {
private int numShapes; // Global scope within the class
public double triangleArea(double base, double height) {
double area = (base * height) / 2; // Local scope within this method
numShapes++;
return area;
}
}
Understanding scope helps in managing variable visibility and avoiding conflicts, leading to more organized and efficient code.
This Keyword
In Java, the this
keyword refers to the current instance of a class. It is used within an object’s methods to access its fields and methods. It helps to distinguish between instance variables and parameters or local variables with the same name and can also be used to pass the current object as a parameter to another method.
Here’s how you can use the this
keyword:
- Accessing Instance Variables: To refer to the current object’s instance variables.
public class MyClass {
int x;
public void setX(int x) {
this.x = x; // Refers to the instance variable
}
}
- Passing the Current Object: To pass the current instance to another method or constructor.
public class MyClass {
int x;
public void setX(int x) {
this.x = x;
}
public void updateX(MyClass obj) {
obj.setX(this.x); // Passing the current object as an argument
}
}
Using this
helps to clarify which variables or methods are being accessed and ensures the correct context for operations on object data.
Additional Resources:
Hacks
Part 1
public class Rectangle {
private double length;
private double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
public double getLength() {
return length;
}
public double getWidth() {
return width;
}
public void setLength(double length) {
this.length = length;
}
public void setWidth(double width) {
this.width = width;
}
public double calculateArea() {
return length * width;
}
}
public class Main {
public static void main(String[] args) {
Rectangle rect1 = new Rectangle(5.0, 3.0);
Rectangle rect2 = rect1;
rect2.setWidth(4.0);
System.out.println("Area of rect1: " + rect1.calculateArea());
}
}
Answer the following questions based on the code above:
- a) What is the output of the
System.out.println("Area of rect1: " + rect1.calculateArea())
statement? Explain why. - Answer:
- b) Do
rect1
andrect2
refer to the same memory location? Explain your answer. - Answer:
Part 2
Situation: You are designing a system to manage employee records in a company. You need to create a class Employee
and another class Company
to manage multiple employees.
(a) Write a class Employee
with private instance variables for name
, id
, and salary
. Include a constructor to initialize these variables, accessor methods to retrieve their values, and mutator methods to update them.
(b) Explain how encapsulation is achieved in the Employee
class. What is the role of accessor and mutator methods in achieving encapsulation?
(c) Code:
Create a class Company
that contains an array of Employee
objects. Include a method addEmployee(Employee newEmployee)
to add a new employee to the array. Write the method signature and implementation, including comments to explain your code.