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. 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. Inheritance is an example of a [[is-a]] relationship. 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. ## 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 is a product of inheritance. Run time polymorphism is called **override**; this is most common. Compile time polymorphism is called **overloading**; this is more common for constructors. **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 overloading Method overloading describes overwriting a method in a superclass within a subclass. For example, the `animal` class may have a default `eat` method, and for some animals a special `eat` method will be written. It's important that the method has the same name for method overloading. Overloading is both dangerous and powerful. If you overload a method by accident or in a way that is inconsistent, the code may break. Overridden methods are subclass methods with the same name and signature as a parent method but different defined behavior. Overloaded methods are subclass methods with the same name as a parent method but a different signature (and likely different behavior). ## 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.