Understanding Classes and Their Components
- Attributes:
- These are the instance variables that define the state of an object.
- For example, a Car class might have attributes like color, make, and model.
- Methods:
- These define the behavior of the class.
- They are functions that operate on the instance variables.
- For example, a Car class might have methods like start(), stop(), and accelerate().
- The attributes will eventually become the instance variables, the data you want to store about the object.
- The behaviors will become the methods, what you need the object to be able to do.
Designing Classes Based on Application Requirements
- Identify the Real-World Entity: Determine what real-world object or concept you are modeling.
- Define Attributes: List the characteristics that are essential to the entity.
- Define Behaviors: Identify the actions the entity can perform or the operations that can be performed on it.
- UML class diagrams show three boxes.
- These contain the name of the class, the instance variables of the class, and the methods of the class.
UML Class Diagram for a Car Class
| Car |
|---|
| - color: String |
| - make: String |
| - model: String |
| - speed: int |
| + start(): void |
| + stop(): void |
| + accelerate(amount: int): void |
| + brake(): void |
When designing classes, always start by identifying the core attributes and behaviors. This ensures your class is both functional and efficient.
Constructing a Class in Code
- Define the Class: Use the class keyword followed by the class name.
- Declare Attributes: Initialize instance variables, often in a constructor method.
- Define Methods: Implement functions that operate on the attributes.
Accessor and mutator methods are essential for maintaining encapsulation, a core principle of OOP.
Accessor and Mutator Methods
Python:
class Student:
def __init__(self, name, age):
self.__name = name # private attribute
self.__age = age
# Accessor (Getter)
def get_name(self):
return self.__name
# Mutator (Setter)
def set_name(self, name):
self.__name = name
# Another Accessor
def get_age(self):
return self.__age
# Another Mutator (with validation)
def set_age(self, age):
if age > 0: # simple validation
self.__age = ageJava:
public class Student {
// Private fields (encapsulation)
private String name;
private int age;
// Constructor
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// Accessor (Getter)
public String getName() {
return name;
}
// Mutator (Setter)
public void setName(String name) {
this.name = name;
}
// Another Accessor
public int getAge() {
return age;
}
// Another Mutator (with validation)
public void setAge(int age) {
if (age > 0) { // simple validation
this.age = age;
}
}
}- When designing methods, always consider the scope and accessibility of your attributes.
- Use private attributes with public accessor and mutator methods to ensure encapsulation.
Modeling Class Relationships in UML
- Aggregation: A "has-a" relationship where the classes can exist independently.
- Example: A Library has Books, but Books can exist without a Library.
- Composition: A stronger "has-a" relationship where the classes cannot exist independently.
- Example: A House has Rooms, and Rooms cannot exist without a House.
- Inheritance: A "is-a" relationship where a subclass inherits attributes and methods from a superclass.
- Example: A Car is a Vehicle.
- Think of aggregation like a university and its students.
- Students can exist without the university, but they are associated with it.
- Composition is like a human body and its organs, organs cannot exist independently of the body.
Designing Classes for Real-World Applications
- Understand the Context: Research the domain to identify relevant attributes and behaviors.
- Use UML Diagrams: Visualize the class structure and relationships before coding.
- Iterate and Refine: Continuously improve your design based on feedback and testing.
| Room |
|---|
| - roomNumber: int |
| - type: String |
| - isOccupied: boolean |
| + checkIn(): void |
| + checkOut(): void |
| + clean(): void |
- When designing classes, always consider the future scalability of your design.
- Ask yourself: Can this class be easily extended or modified if requirements change?