A class is a way of representing an object with code. A class defines a type with a legal set of values. An objects is an **instance** of a class.
## constructors
Classes control how their objects are created and destroyed. The constructor method is a special method for creating a new instance. Constructors ensure the object is properly initialized before any object makes use of it.
## destructors
Like constructors, destructors handle the destruction or **finalization** of a class instance. This ensures the object releases all of its resources once it is no longer active. In garbage collected languages, this can be especially important to avoid objects hanging on to resources for a long time.
## inheritance
A **subclass** can be defined that includes some elements of the **superclass**; this is called **inheritance**. The subclass can be treated as if it is the superclass, such that code that is built to process the superclass can also apply to the subclass.
Inheritance is an example of a [[is-a]] relationship.
## abstract class
When a superclass is never truly used, but rather serves as a template for multiple subclasses, is known as an **abstract** class. Abstract classes typically have no initiation method to signify their status as abstract. Classes that are instantiated are **concrete** classes.
## interface
An **interface** is a helper class that groups behaviors that might be relevant to some but not all instances of the class. **Generic components** fulfill a similar role.
## function interface
The interface of a function or object include what it accepts and what it returns. This "input/output" thinking is an important first step in designing code and a very helpful exercise if you get stuck.
## polymorphism
Polymorphism is "being able to refer to different derivations of a class in the same way, but getting the behavior appropriate to the derived class being referred to."
-Shalloway/Trott
Polymorphism takes different forms:
- **Subtype (runtime) polymorphism**: achieved through inheritance. A parent reference can point to child objects, and method **overriding** ensures the correct behavior is called at runtime.
- **Ad hoc (compile-time) polymorphism**: achieved via **method overloading** or **operator overloading**, where multiple methods share the same name but differ by parameters or context.
- **Parametric polymorphism**: achieved through generics/templates (not built into Python directly).
## operator overloading
**Operator overloading** is allowed by some languages like [[Python]]. This allows overloading for example the `__repr__` or `__add__` operators for an object (which change what `print()` and `+` do for the object, respectively).
## method overriding
Method overriding happens when a subclass redefines a method from its superclass with the **same name and same signature** but different behavior.
Example:
```python
class Animal:
def speak(self):
return "Some sound"
class Dog(Animal):
def speak(self): # override
return "Woof!"
```
## method overloading
Method overloading means defining multiple methods with the same name but different signatures (number or type of parameters).
Method overloading is supported in languages like Java and C++ (at compile time). Python does not support true method overloading. Instead, you can simulate it with default arguments, `*args`.
Example in Java:
```Java
class Calculator {
// Add two integers
int add(int a, int b) {
return a + b;
}
// Add two doubles
double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(5, 10)); // calls int add
System.out.println(calc.add(5.5, 2.3)); // calls double add
}
}
```
Overloading is both dangerous and powerful. If you overload a method by accident or in a way that is inconsistent, the code may break.
## delegation
Delegation is when some other class already exists to handle a request. The host class delegates this request to the existing class. A common example might be using a method in an existing library within a class (e.g., call `requests` inside a class that reads a web page).
Delegation is an example of a [[has-a]] relationship.
In OOP, we **favor delegation over inheritance**.
## levels of accessibility
Class features can be public, protected, and private.
- **Public**: accessible from any code
- **Protected**: accessible only within the class and its subclasses
- **Private**: accessible only within the defining class
Different programming languages have different implementations of these levels of accessibility.