Can't seem to understand SOLID principles and design patterns [closed] - oop

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I'm trying to get into OOP lately, and I'm having trouble with SOLID principles and design patterns. I see why people use them, and I really want to use them too, but I can't wrap my head around developing my classes to the specifications. I would really appreciate anything that would help my understanding of such.

I've taken a class in college that spent two weeks around design patters, and read the Gang of Four book to no avail. Understanding what each pattern served for and how to use them to fit my problems was very hard for me, a developer that didn't have much experience in OO programming.
The book that really made it click for me was Head First Design Patterns. It starts by showing a problem, different approaches the developers considered, and then how they ended up using a design pattern in order to fix it. It uses a very simple language and keeps the book very engaging.
Design patterns end up being a way to describe a solution, but you don't have to adapt your classes to the solution. Think of them more as a guide that suggest a good solution to a wide array of problems.
Let's talk about SOLID:
Single responsibility. A class should have only one responsibility. That means that for example, a Person class should only worry about the domain problem regarding the person itself, and not for example, its persistence in the database. For that, you may want to use a PersonDAO for example. A Person class may want to keep its responsibilities the shortest it can. If a class is using too many external dependencies (that is, other classes), that's a symptom that the class is having too many responsibilities. This problem often comes when developers try to model the real world using objects and take it too far. Loosely coupled applications often are not very easy to navigate and do not exactly model how the real world works.
Open Closed. Classes should be extendible, but not modifiable. That means that adding a new field to a class is fine, but changing existing things are not. Other components on the program may depend on said field.
Liskov substitution. A class that expects an object of type animal should work if a subclass dog and a subclass cat are passed. That means that Animal should NOT have a method called bark for example, since subclasses of type cat won't be able to bark. Classes that use the Animal class, also shouldn't depend on methods that belong to a class Dog. Don't do things like "If this animal is a dog, then (casts animal to dog) bark. If animal is a cat then (casts animal to cat) meow".
Interface segregation principle. Keep your interfaces the smallest you can. A teacher that also is a student should implement both the IStudent and ITeacher interfaces, instead of a single big interface called IStudentAndTeacher.
Dependency inversion principle. Objects should not instantiate their dependencies, but they should be passed to them. For example, a Car that has an Engine object inside should not do engine = new DieselEngine(), but rather said engine should be passed to it on the constructor. This way the car class will not be coupled to the DieselEngine class.

Related

Abstraction in OOP: multiple, yet rather distinct, contexts? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I've been doing some research on OOP concepts and am having a bit of an issue in trying to understand what exactly Abstraction is. I've gone over numerous Stack Overflow posts on the topic but haven't really been able to pinpoint a satisfying answer.
I've seen a lot of discussions on the differences between Abstraction and Encapsulation, and naturally started started thinking about Abstraction in terms of hiding how a particular class works and providing abstraction through the class API. Here are some posts that steered me in this direction:
Best voted answer refers to functions being Abstract. The very next answer starts talking about abstract classes...
Best voted answer seems to refer to exposing through the class API while the next two goes off in an Inheritance setting. Third answer even suggests Composition and Aggregation is considered an Abstraction
However, as I read through more posts, I noticed answers portraying Abstraction in an Inheritance context, specifically using interfaces and abstract classes to provide an Abstraction of a certain entity (class). I assumed Abstraction given in this manner would allow developers to extend new objects appropriately according to the "guidelines" outlined by this Abstraction. Here are some posts that lead me in this direction:
First couple of answers talk about Abstraction in an abstract class/interface setting, while some down the line start talking about exposing classes through APIs
Top two voted answers refer to abstract classes/interfaces
I'm not sure if I'm just completely missing the point here, but it's getting pretty confusing because every answer seems to add a slight variation to the mix. I definitely see why both contexts are crucial in Object Oriented Programming, but I really wanted a clear-cut definition of what Abstraction is.
Which brings me to my point: does Abstraction work in multiple contexts? Does Abstraction portray both of these concepts?
Hiding away "unnecessary details" as done through interfaces and
abstract classes
Providing an abstraction on a class to be created through interfaces and abstract classes. We can provide an interface of IPet which would act as an abstraction of a Dog class. Additionally, we could provide an Animal base class as an abstract class to provide a higher level abstraction. This could let us use Polymorphism and allow different classes that fall under our Animal abstraction to interact with one another.
Abstracting the implementation of a class by exposing it through the class API
given a Dog class, we just need to know that it has a feed() function as part of its API, and call that function to feed it without knowing how the feeding is actually done. This provides abstraction on the Dog class and lets us easily interact with the class
One of the links I've included above contains the following quote by Matthew Watson that says:
"The problem is that there are no precise definitions for these concepts, and the words themselves have multiple meanings even within the context of object orientation."
Is it just that Abstraction is so abstract, even the definition is abstract :P? Thanks for any guidance in advance!
Edit: I'm rather new to SO and am not really aware of what the "primarily opinion based" flag entails. I don't see how this question is any less valid than the slew of questions regarding Abstraction on SO. I think it would be considered less opinion-based as I'm actually pinpointing two different contexts in which I think Abstraction makes sense in. I've seen many questions that just ask what Abstraction is, which I'd think is an even broader question than what I have here.
To me, abstraction is one of the most beautiful concepts of oo, which is actually what makes the program language very close to human thinking: we, humans always want to classify. Think of a car: your car. And let's approach that car in the context of a banker asking about your assets in the context of a loan: you will say you have assets (highest level of abstraction): an expensive car, a family car, a house, a boat, etc. They all have a specific value. Then suppose the context of the conversation switches to the banker having a personal interest in that car, given he's a car freak him selves. Now the cars will be described in more detail, and you can see different abstraction levels being defined: sport car with brand names, and lots more characteristics.
During the design time, your interest is about the levels of abstraction: What you want to do with it, i.e. its context. So, we will have the levels of abstraction: Asset, Car (and Boat and House), SportCar, FamilyCar. And so on. The context should never have more details than it needs, and this is what you're concerned about during design phase.
During the implementation phase, you will implement these levels of abstraction by encapsulating the properties that belong at these levels. E.g. Asset has a value, where Car has colour and SportCar might have some specific characteristics that a FamilyCar doesn't have.
So, key difference is: design time vs implementation time.
This blog post described the difference in much detail:
http://javarevisited.blogspot.be/2017/04/difference-between-abstraction-and-encapsulation-in-java-oop.html
Here's another post at stackoverflow: What's the difference between abstraction and encapsulation?
Hope this helps.
As for me, the abstraction is when you solve a problem without going into the details at all. If you need to output list of cars, then I do not think "take a list of cars, walk through them, get their data, print them", I rather think "I need a set of objects, preferably cars, that can display data about themselves in the format that I need.". It's more about way of thinking.

Is Scala mixin really better than multiple C++ inheritance? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
People say C++ inheritance is evil, so Java 'fixed' this problem with interface.
But Scala introduced traits, they're... interface with partial implementation? Doesn't this brought multiple inheritance back?
Does it mean Scala guys think multiple inheritance is good? Or They have some critical differences I haven't noticed?
The worst part of multiple inheritance is diamond inheritance, where a subclass has two or more paths to the same parent somewhere up the chain. This creates ambiguity if implementations differ along the two paths (i.e. are overridden from the original implementation). In C++ the solution is particularly ugly: you embed both incompatible parent classes and have to specify when you call which implementation you want. This is confusing, creates extra work at every call site (or, more likely, forces you to override explicitly and state the one you want; this manual work is tedious and introduces a chance for error), and can lead to objects being larger than they ought to be.
Scala solves some but not all of the problems by limiting multiple inheritance to traits. Because traits have no constructors, the final class can linearize the inheritance tree, which is to say that even though two parents on a path back to a common super-parent nominally are both parents, one is the "correct" one, namely the one listed last. This scheme would leave broken half-initialized classes around if you could have (completely generic) constructors, but as it is, you don't have to embed the class twice, and at the use site you can ignore how much inheritance if any has happened. It does not, however, make it that much easier to reason about what will happen when you layer many traits on top of each other, and if you inherit from both B and C, you can't choose to take some of B's implementations and the some of C's.
So it's better in that it addresses some of the most serious criticisms of the C++ model. Whether it is better enough is a matter of taste; plenty of people even like the taste of C++'s multiple inheritance well enough to use it.

How to restructure/redesign an ever growing adapter class? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am working on a game/simulation application that uses multiple mathematical solvers. There is an already existing adapter class for each of them. These adapter classes provide all rendering and functional information for the application.
Broadly speaking, we keep an adapter object to represent an instance and call methods to achieve:
Generate rendering data.
modify object state. There are just too many function to do it.
read data model information for various purposes.
Now the problem is that these classes keep growing over a period of time and carry too much information and responsibility.
My question is how can I redesign/restructure these classes to make better sense. Is there any design pattern I should be looking at?
Edit: As requested, here is the broad list of things any adapter class will be doing.
Sync with the current data stored in mathematical solver.
Sync with the data model of our application. For things like
undo/redo.
Modify object state: Change in shape. This is most important and have
various, more than 50, functions to achieve it. All are self
contained single service call with parameters. I am trying to insert
interfaces and factory here but function signatures are not
compatible.
Get data model information of mathematical solver. Like getChildern
etc.
Change visibility and other graphic property.
The principle to use would be Information Expert from GRASP:
[…] Using the principle of Information Expert, a general approach to assigning responsibilities is to look at a given responsibility, determine the information needed to fulfill it, and then determine where that information is stored. Information Expert will lead to placing the responsibility on the class with the most information required to fulfill it. […]
Though never explicitly mentioned, applying this principle will likely lead you to using the patterns given by Martin Fowler in the chapter Moving Features Between Objects in his Refactoring book:
[…] Often classes become bloated with too many responsibilities. In this case I use Extract Class to separate some of these responsibilities. If a class becomes too irresponsible, I use Inline Class to merge it into another class. If another class is being used, it often is helpful to hide this fact with Hide Delegate. Sometimes hiding the delegate class results in constantly changing the owner’s interface, in which case you need to use Remove Middle Man […]
In general, break down your classes so that each only has one reason to change, per the Single Responsibility Principle. Leave your "adapters" in place as a Facade over the classes you'll extract; it will make the refactor smoother.
Since you describe a list of responsibilities that are common to all your adapters, you probably have a lot of code that is almost the same between the adapters. As you go through this exercise, try extracting the same responsibility from several adapters, and watch for ways to eliminate duplication.
It would be tempting to start with extracting a class for "Modify Object state". Since you have more than 50 (!) functions fulfilling that responsibility, you should probably break that down into several classes, if you can. As this is likely the biggest cause of bloat in your adapter class, just doing it may solve the problem, though it will be important to break it down or you'll just move the God class, instead of simplifying it.
However, this will be a lot of work and it will likely be complex enough that you won't easily see opportunities for reuse of the extracted classes between adapters. On the other hand, extracting small responsbilities won't get you a lot of benefit. I would pick something in the middle to start.

When there is a class Car, should a car that is convertible subclass Car or not? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Say, if in our object design, there is already a Car class, and now there are some cars objects that convertibles.
We can define another class Convertible and subclass Car, but then let's say, we later on create a class that's FourWheelDrive that also subclasses Car, and later on, if we have a FourWheelDrive that is also a Convertible, then how can we handle it?
How is the design above compared with the other design, which is a isConvertible boolean in the Car class, and a isFourWheelDrive boolean also in the Car class, just as flags or properties of the Car class. So we won't define extra classes in this case.
Update: in a real life example, in our project, there was a Credential class that stores a user's info: user_id, encrypted_password, email_address, etc. When we allow logging in through Facebook, Gmail, Yahoo, MySpace (using JanRain), a coworker proposed adding FacebookCredential, GmailCredential, YahooCredential, all these classes that subclass Credential. I was a bit overwhelmed that there are so many classes, and when you see a method, you have to look at whether the subclass overrides it or is it the base class's method. I would have done it just using a code to tell which provider of the credential it is (Facebook, Gmail, etc), and use this provider code to do the appropriate things. (for example, some providers have verified email address, some don't). So I just don't know if my coworker's method is more appropriate or complicated.
You might want to take a different approach by using the http://en.wikipedia.org/wiki/Strategy_pattern
You can define different behaviours for diffrent types of cars, so you don't have lots of subclasses.
You imply that you're using a language which doesn't support multiple inheritance. Does the language support interfaces? You could have a base abstract class Car. (Abstract because one never builds a "car" but instead builds a specific implementation of a car.) Then instances of classes which inherit the abstract base class can implement common interfaces:
IConvertible
IFourWheelDrive
IHybrid
and so on...
The idea is that the abstract base class defines what something is at its simplest. The interfaces define what type of that thing it is, and there can certainly be overlap. Those interfaces would contain the operations and properties which are specific to that type. (An IConvertible would have properties and methods that non-convertibles wouldn't have, same with an IHybrid, etc.) Then the specific implementations could add their own unique flair to the whole thing.
It's a bit of a contrived example, as you know. So it's all conjecture. But for this particular theoretical implementation I'd go with interfaces.
In addition to your concern about four wheel drive cars which are also convertibles, consider the following:
Are all Convertables cars?
Are all vehicles with four wheel drive cars?
To me, these sorts of questions point at these being attributes of car which do not define a type. In a sense, they're no different than color or the number of doors, etc.
It basically comes down to a question whether you need/want to change the functionality of the class based on whether it's a convertible and or four wheel-drive. For example, if you need/want to have a raise_top and lower_top for a convertible, and lock_hubs and unlock_hubs for a four wheel-drive, then you pretty much need to use inheritance to add classes that have those. In such a case, then yes, there's a pretty fair chance that an open-top 4WD vehicle will inherit from both the convertible and 4 wheel-drive classes. As such, if you're doing that in C++, those classes should probably inherit virtually from automobile (or whatever you name your base class), and in something like Java, they'll pretty much need to be interfaces rather than classes.
On the other hand, if you just need to be able to find out whether a particular vehicle is or isn't convertible and/or 4 wheel-drive, then a simple Boolean (or enumerated) field in the class should be perfectly adequate.

Inheritance vs. Aggregation [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
There are two schools of thought on how to best extend, enhance, and reuse code in an object-oriented system:
Inheritance: extend the functionality of a class by creating a subclass. Override superclass members in the subclasses to provide new functionality. Make methods abstract/virtual to force subclasses to "fill-in-the-blanks" when the superclass wants a particular interface but is agnostic about its implementation.
Aggregation: create new functionality by taking other classes and combining them into a new class. Attach an common interface to this new class for interoperability with other code.
What are the benefits, costs, and consequences of each? Are there other alternatives?
I see this debate come up on a regular basis, but I don't think it's been asked on
Stack Overflow yet (though there is some related discussion). There's also a surprising lack of good Google results for it.
It's not a matter of which is the best, but of when to use what.
In the 'normal' cases a simple question is enough to find out if we need inheritance or aggregation.
If The new class is more or less as the original class. Use inheritance. The new class is now a subclass of the original class.
If the new class must have the original class. Use aggregation. The new class has now the original class as a member.
However, there is a big gray area. So we need several other tricks.
If we have used inheritance (or we plan to use it) but we only use part of the interface, or we are forced to override a lot of functionality to keep the correlation logical. Then we have a big nasty smell that indicates that we had to use aggregation.
If we have used aggregation (or we plan to use it) but we find out we need to copy almost all of the functionality. Then we have a smell that points in the direction of inheritance.
To cut it short. We should use aggregation if part of the interface is not used or has to be changed to avoid an illogical situation. We only need to use inheritance, if we need almost all of the functionality without major changes. And when in doubt, use Aggregation.
An other possibility for, the case that we have an class that needs part of the functionality of the original class, is to split the original class in a root class and a sub class. And let the new class inherit from the root class. But you should take care with this, not to create an illogical separation.
Lets add an example. We have a class 'Dog' with methods: 'Eat', 'Walk', 'Bark', 'Play'.
class Dog
Eat;
Walk;
Bark;
Play;
end;
We now need a class 'Cat', that needs 'Eat', 'Walk', 'Purr', and 'Play'. So first try to extend it from a Dog.
class Cat is Dog
Purr;
end;
Looks, alright, but wait. This cat can Bark (Cat lovers will kill me for that). And a barking cat violates the principles of the universe. So we need to override the Bark method so that it does nothing.
class Cat is Dog
Purr;
Bark = null;
end;
Ok, this works, but it smells bad. So lets try an aggregation:
class Cat
has Dog;
Eat = Dog.Eat;
Walk = Dog.Walk;
Play = Dog.Play;
Purr;
end;
Ok, this is nice. This cat does not bark anymore, not even silent. But still it has an internal dog that wants out. So lets try solution number three:
class Pet
Eat;
Walk;
Play;
end;
class Dog is Pet
Bark;
end;
class Cat is Pet
Purr;
end;
This is much cleaner. No internal dogs. And cats and dogs are at the same level. We can even introduce other pets to extend the model. Unless it is a fish, or something that does not walk. In that case we again need to refactor. But that is something for an other time.
At the beginning of GOF they state
Favor object composition over class inheritance.
This is further discussed here
The difference is typically expressed as the difference between "is a" and "has a". Inheritance, the "is a" relationship, is summed up nicely in the Liskov Substitution Principle. Aggregation, the "has a" relationship, is just that - it shows that the aggregating object has one of the aggregated objects.
Further distinctions exist as well - private inheritance in C++ indicates a "is implemented in terms of" relationship, which can also be modeled by the aggregation of (non-exposed) member objects as well.
Here's my most common argument:
In any object-oriented system, there are two parts to any class:
Its interface: the "public face" of the object. This is the set of capabilities it announces to the rest of the world. In a lot of languages, the set is well defined into a "class". Usually these are the method signatures of the object, though it varies a bit by language.
Its implementation: the "behind the scenes" work that the object does to satisfy its interface and provide functionality. This is typically the code and member data of the object.
One of the fundamental principles of OOP is that the implementation is encapsulated (ie:hidden) within the class; the only thing that outsiders should see is the interface.
When a subclass inherits from a subclass, it typically inherits both the implementation and the interface. This, in turn, means that you're forced to accept both as constraints on your class.
With aggregation, you get to choose either implementation or interface, or both -- but you're not forced into either. The functionality of an object is left up to the object itself. It can defer to other objects as it likes, but it's ultimately responsible for itself. In my experience, this leads to a more flexible system: one that's easier to modify.
So, whenever I'm developing object-oriented software, I almost always prefer aggregation over inheritance.
I gave an answer to "Is a" vs "Has a" : which one is better?.
Basically I agree with other folks: use inheritance only if your derived class truly is the type you're extending, not merely because it contains the same data. Remember that inheritance means the subclass gains the methods as well as the data.
Does it make sense for your derived class to have all the methods of the superclass? Or do you just quietly promise yourself that those methods should be ignored in the derived class? Or do you find yourself overriding methods from the superclass, making them no-ops so no one calls them inadvertently? Or giving hints to your API doc generation tool to omit the method from the doc?
Those are strong clues that aggregation is the better choice in that case.
I see a lot of "is-a vs. has-a; they're conceptually different" responses on this and the related questions.
The one thing I've found in my experience is that trying to determine whether a relationship is "is-a" or "has-a" is bound to fail. Even if you can correctly make that determination for the objects now, changing requirements mean that you'll probably be wrong at some point in the future.
Another thing I've found is that it's very hard to convert from inheritance to aggregation once there's a lot of code written around an inheritance hierarchy. Just switching from a superclass to an interface means changing nearly every subclass in the system.
And, as I mentioned elsewhere in this post, aggregation tends to be less flexible than inheritance.
So, you have a perfect storm of arguments against inheritance whenever you have to choose one or the other:
Your choice will likely be the wrong one at some point
Changing that choice is difficult once you've made it.
Inheritance tends to be a worse choice as it's more constraining.
Thus, I tend to choose aggregation -- even when there appears to be a strong is-a relationship.
The question is normally phrased as Composition vs. Inheritance, and it has been asked here before.
I wanted to make this a comment on the original question, but 300 characters bites [;<).
I think we need to be careful. First, there are more flavors than the two rather specific examples made in the question.
Also, I suggest that it is valuable not to confuse the objective with the instrument. One wants to make sure that the chosen technique or methodology supports achievement of the primary objective, but I don't thing out-of-context which-technique-is-best discussion is very useful. It does help to know the pitfalls of the different approaches along with their clear sweet spots.
For example, what are you out to accomplish, what do you have available to start with, and what are the constraints?
Are you creating a component framework, even a special purpose one? Are interfaces separable from implementations in the programming system or is it accomplished by a practice using a different sort of technology? Can you separate the inheritance structure of interfaces (if any) from the inheritance structure of classes that implement them? Is it important to hide the class structure of an implementation from the code that relies on the interfaces the implementation delivers? Are there multiple implementations to be usable at the same time or is the variation more over-time as a consequence of maintenance and enhancememt? This and more needs to be considered before you fixate on a tool or a methodology.
Finally, is it that important to lock distinctions in the abstraction and how you think of it (as in is-a versus has-a) to different features of the OO technology? Perhaps so, if it keeps the conceptual structure consistent and manageable for you and others. But it is wise not to be enslaved by that and the contortions you might end up making. Maybe it is best to stand back a level and not be so rigid (but leave good narration so others can tell what's up). [I look for what makes a particular portion of a program explainable, but some times I go for elegance when there is a bigger win. Not always the best idea.]
I'm an interface purist, and I am drawn to the kinds of problems and approaches where interface purism is appropriate, whether building a Java framework or organizing some COM implementations. That doesn't make it appropriate for everything, not even close to everything, even though I swear by it. (I have a couple of projects that appear to provide serious counter-examples against interface purism, so it will be interesting to see how I manage to cope.)
I'll cover the where-these-might-apply part. Here's an example of both, in a game scenario. Suppose, there's a game which has different types of soldiers. Each soldier can have a knapsack which can hold different things.
Inheritance here?
There's a marine, green beret & a sniper. These are types of soldiers. So, there's a base class Soldier with Marine, Green Beret & Sniper as derived classes
Aggregation here?
The knapsack can contain grenades, guns (different types), knife, medikit, etc. A soldier can be equipped with any of these at any given point in time, plus he can also have a bulletproof vest which acts as armor when attacked and his injury decreases to a certain percentage. The soldier class contains an object of bulletproof vest class and the knapsack class which contains references to these items.
I think it's not an either/or debate. It's just that:
is-a (inheritance) relationships occur less often than has-a (composition) relationships.
Inheritance is harder to get right, even when it's appropriate to use it, so due diligence has to be taken because it can break encapsulation, encourage tight coupling by exposing implementation and so forth.
Both have their place, but inheritance is riskier.
Although of course it wouldn't make sense to have a class Shape 'having-a' Point and a Square classes. Here inheritance is due.
People tend to think about inheritance first when trying to design something extensible, that is what's wrong.
Favour happens when both candidate qualifies. A and B are options and you favour A. The reason is that composition offers more extension/flexiblity possiblities than generalization. This extension/flexiblity refers mostly to runtime/dynamic flexibility.
The benefit is not immediately visible. To see the benefit you need to wait for the next unexpected change request. So in most cases those sticked to generlalization fails when compared to those who embraced composition(except one obvious case mentioned later). Hence the rule. From a learning point of view if you can implement a dependency injection successfully then you should know which one to favour and when. The rule helps you in making a decision as well; if you are not sure then select composition.
Summary: Composition :The coupling is reduced by just having some smaller things you plug into something bigger, and the bigger object just calls the smaller object back. Generlization: From an API point of view defining that a method can be overridden is a stronger commitment than defining that a method can be called. (very few occassions when Generalization wins). And never forget that with composition you are using inheritance too, from a interface instead of a big class
Both approaches are used to solve different problems. You don't always need to aggregate over two or more classes when inheriting from one class.
Sometimes you do have to aggregate a single class because that class is sealed or has otherwise non-virtual members you need to intercept so you create a proxy layer that obviously isn't valid in terms of inheritance but so long as the class you are proxying has an interface you can subscribe to this can work out fairly well.