Composition, Inheritance, and their differences with examples – Ruby

Let’s break down composition, inheritance, and their differences with examples.

### Composition:

**Definition:**
Composition is a principle in object-oriented programming (OOP) that allows one class to contain instances of another class as members. This means that one class can use the functionalities provided by another class without inheriting from it.

**Example:**
Imagine you’re building a car. Instead of making the car a subclass of an “Engine” class, you create an instance of an “Engine” class inside the “Car” class. This way, the car contains an engine, but it’s not derived from it.

```ruby
class Engine
def start
puts "Engine started!"
end
end

class Car
def initialize
@engine = Engine.new
end

def start_engine
@engine.start
end
end

my_car = Car.new
my_car.start_engine # Output: "Engine started!"
```

In this example, `Car` has a composition relationship with `Engine`.

### Inheritance:

**Definition:**
Inheritance is another OOP principle where one class (child or subclass) can inherit attributes and behaviors from another class (parent or superclass). The child class can extend or override these attributes and behaviors.

**Example:**
Let’s say you have a base class `Animal`:

```ruby
class Animal
def move
puts "Moving..."
end
end
```

You can create a subclass `Dog` that inherits from `Animal`:

```ruby
class Dog < Animal
def bark
puts "Woof!"
end
end
```

Now, a `Dog` has the ability to move (inherited from `Animal`) and bark.

### Composition vs. Inheritance:

#### Composition:
– **Flexibility**: With composition, you can change the behavior of a class at runtime by switching the object it contains.
– **Loose Coupling**: Classes are less dependent on each other. Changes in one class don’t necessarily affect the other.
– **Complex Behavior**: It allows you to create complex behaviors by combining different objects.

#### Inheritance:
– **Code Reusability**: You can reuse code from the parent class in the child class.
– **Hierarchical Structure**: It establishes a hierarchy, which can be useful for modeling real-world relationships.
– **Method Overriding**: You can override methods from the parent class in the child class.

### Example:

Let’s consider an example where we have `Vehicle` as a base class and `Car` as a subclass:

#### Using Inheritance:

```ruby
class Vehicle
def start_engine
puts "Engine started!"
end
end

class Car < Vehicle
def drive
puts "Car is moving."
end
end

my_car = Car.new
my_car.start_engine # Output: "Engine started!"
my_car.drive # Output: "Car is moving."
```

#### Using Composition:

```ruby
class Engine
def start
puts "Engine started!"
end
end

class Car
def initialize
@engine = Engine.new
end

def drive
puts "Car is moving."
end

def start_engine
@engine.start
end
end

my_car = Car.new
my_car.start_engine # Output: "Engine started!"
my_car.drive # Output: "Car is moving."
```

### Conclusion:

– **Composition** is like building with LEGO blocks. You assemble different pieces to create a whole.
– **Inheritance** is like extending a family tree. Children inherit characteristics from their parents.

Choosing between composition and inheritance depends on the specific requirements of your program. Composition is often favored because it provides more flexibility and reduces dependencies between classes. However, both have their own strengths and can be used together in a well-designed system.

Leave a Reply