Advanced programming concepts summary
Concept Definition
Abstraction Abstraction is a process that deals with complexity by hiding unnecessary information from the user. It simplifies reality by creating a version of an object that consists only of essential information. Data is visible only to semantically related functions to prevent misuse. Example: We can do many things on a computer, but it doesn't show us how it's doing them because we don't need that information. The implementation parts are hidden. It is the first concept of object-oriented programming.
Encapsulation Encapsulation prevents external code from being concerned with the internal workings of an object. It involves hiding the fields and methods of a class so that they are not accessible from the outside but only inside the class. The difference between abstraction and encapsulation is that abstraction hides objects and processes to show only the result at the end because it is the only thing that matters, while encapsulation hides them and blocks access to them, e.g., because some data should not be changed directly without a setter with validation rules inside. Encapsulation also promotes the creation of small, specialized methods and classes to keep them easy to understand, maintain, and reuse. It is the second concept of object-oriented programming. We should always identify the part of the code that changes and, when possible, encapsulate it.
Inheritance Classes can inherit objects (methods) from each other. The class that is being inherited from is called a parent class (also a base class or a superclass). The class that inherits from another class is called a child class (also a derived class or a subclass). It is the third concept of object-oriented programming.
Polymorphism Polymorphism means operating in the same way on objects of different types. It refers to an object's ability to take on many forms. For example, the + operator behaves polymorphically because it can add numbers and concatenate strings (it works with various data types in a very similar way). It is the fourth concept of object-oriented programming. Example: A man can be a father, a husband, a student, etc. One person can have different roles.
Static variables A static variable is a variable that won't be deleted while "exiting" a method (its address is reserved only once). A variable of this type will still exist even if an instance of the class does not. It is shared by all objects and not tied to any class instance (shared across all instances of the class). We create static variables outside methods. A static variable is also called a class attribute.
Static methods The same rule as with static variables applies to methods. We can call static methods using the class directly without creating its instance (like class methods). They have no access to the class's objects, which makes them essentially ordinary functions within the class. Static methods differ from outside functions because we can override them later in a child class.
Abstract methods An abstract class is a class that is designed specifically to be used as a base class (e.g., creating an instance of a generic Vehicle wouldn’t make sense unless it’s a specific type like a Car or Truck). It can't call out its own objects or have instances, so we can only use them in its child classes. An abstract class provides an API that we are expected to implement in its child classes (acting as a blueprint for the functionality). We create abstract objects by adding the abstract keyword before their type. An abstract method is a method that is inside an abstract class and has the abstract keyword before its type. An abstract class forces all its child classes to override all its abstract methods. It isn't mandatory to override a non-abstract method from an abstract class. Abstract methods can't contain any implementation, providing only method signatures that must be implemented by subclasses. Non-abstract methods can contain implementations to be inherited in the child classes (abstract methods have to be overridden, so it wouldn't make sense for them to contain implementations). If an abstract class contains a constructor, it will be executed when its subclass is instantiated.
Method overloading Two methods can have the same name as long as they have a different number of arguments and/or they have various types. This behavior is called method overloading. For example, if we provide two double arguments to an addition() method, the compiler will know that we want to use the specific version of the method that takes those arguments and not, e.g., the one that takes two integers. The two overloaded functions have to differ in number or type of arguments, and can, but do not have to, have a different return type.
Overloading operators Overloading an operator means overriding its functionalities so it can work with, e.g., our class's objects. In Java, we cannot overload operators directly as we do in languages like C++ (e.g., ==, <<). Here, we override methods corresponding to the operators (e.g., equals() equals ==). The toString() method defines how a class object will be displayed when printed or converted to a string (using toString()).
Downcasting Downcasting is when we have an object stored as its parent type, but cast it back to its child type to access methods that only exist in the child class. It means more or less "reverse inheritance".
Composition Inheritance is used for is a relationships (e.g., a cat is an animal), and composition is used for has a relationships (e.g., a house has rooms). It involves attaching objects to a class instead of inheriting a whole class of these objects.
Aggregation The difference between aggregation and composition is the degree of ownership of the existing class. Aggregation implies a relationship where the child class can exist independently of the parent class (cars are not a part of a car park). Example: school and students. Delete the school, and the students will still exist. Composition implies a relationship where the child cannot exist independently of the parent (e.g., wheels are a part of a car).
Nested classes We can put classes in each other. This solution is used for logically grouping related classes, enhancing encapsulation by restricting visibility to the outer class, and improving code organization. Inner classes have access to the outer class's objects.
Anonymous classes Anonymous classes allow us to declare and instantiate a class at the same time, in a single expression, without giving it a name. They are typically used to provide a one-off implementation of an interface or abstract class inline, eliminating the need to define a separate named class. Anonymous classes can access variables from their enclosing scope, provided those variables are final or effectively final (a variable that is never reassigned after its initial assignment).
Threads A thread is a unit of execution within a process that allows tasks to run concurrently, sharing the same memory space.