I have been reading about inheritance vs composition. I know there is already allot about this topic on this site, but i have a question about this specific example I hope will not be seen as duplicate.
Some guidelines I have gathered so far:
Prefer composition over inheritance.
Has-a relationship will therefore almost always mean composition.
Is-a relationship CAN mean inheritance is best, but not always.
So now for the example
I have been working on a simple game engine to practice C++. For this I have made some classes:
The Image class that contains an image that can be rendered.
The Transform class is all about positioning.
The Sprite class contains an image that can be rendered, in a specific position.
There is more of course, but let’s keep it simple for the example.
So - Sprite HAS an image and HAS a position (transform). Following the guideline that would mean composition for both. BUT I think it is just so much easier to have Sprite inherit from Transform.
Because I what to do things sprite->setPosition() and sprite ->setScale().
If a Sprite inherits from Transform, I don’t have to do anything, sprite->setPosition() automatically calls Transform::setPosition() for the sprite object.
If Sprite HAS a Transform, I would have to redirect ALL of these kind of methods to the Transform! (It's how I have been doing it so far and it seems to work fine)
I don’t want to write things like this for every positioning method: (there are quite a few already)
Sprite::setPosition(Vector2 position) {
mTransform.setPosition(Vector2 position);
}
But It seems to go against convention.
What do you all think?
When you say "easier" I think you mean "faster", because let's face it, forwarding the calls from the Sprite to the Transform component it's not difficult at all, it just takes more typing (and "less typing" is good, but I would weigh other things first). The problems of choosing inheritance over composition could not be there now, but could arise later.
With public inheritance you just have to declare the inheritance, and all the public interface from Transform is available in Sprite. All. If one day you add a "Rotate" method to the Transform, but don't want Sprites to be shown upside down, then you have to hide the base class method somehow. There are good answers here from Matthieu and CodeFirst about how to do that hiding in C++. But as Matthieu points there, by hiding the method you violate the Liskov Substitution Principle. If you had used composition, you could have just ignored that "Rotate" method in the public interface for Sprite.
With private inheritance you would be a little bit better, because it represents a "is implemented in terms of" relationship between Sprite and Transform, closer to reality than the "is a" relationship represented by public inheritance. But then you would need to put "using" statements to make available the methods from Transform in Sprite (see Eugen answer also in the previous link). So you end up still having to write extra code to achieve your purpose (although less than with composition).
With composition I feel that you have easier options to deal with design problems. Do you want to simply call the component method? You forward the call. Do you want to ban the component method? You don't add it to the Sprite interface. Do you want to add functionality to one method (e.g. keeping the Transform scale from being set to such value that the size of the Sprite Image is too small)? You add the method to the interface but do some extra processing/checkings before/after calling the Transform component...
If you can get your hands on Scott Meyers' Effective C++ book, you have two items that are worth reading for this discussion: "Use private inheritance judiciously" and "Model 'has-a' or 'is-implemented-in-terms-of' through composition". A final point extracted from there in favor of composition: "Both composition and private inheritance mean is-implemented-in-terms-of, but composition is easier to understand, so you should use it whenever you can"
I am trying to understand how object interactions are programmed.
I think I understand the basic principle that an object has methods that have access to its data and can change it. But what if two objects interact and something object1 does has to change the state of object2.
Say you have a Person object and a Ball object and the Person has to kick the ball, thus changing the coordinates of the ball.
Would it look something like:
person.kick(ball)
where person.kick looks like
kick(whatToKick) {
whatToKick.changeCoord();
}
Is this at all correct?
Should an objects state only be changed by its own methods?
Is the pattern for object interaction always:
Passing a reference of object1 to object2
Having object2's method call object1's methods to retrieve or change object1's state?
Also if anybody could recommend a book on OOP principles and design patterns that would be very nice.
Thanks.
Basically, what you wrote is correct:
The state of an object should only be modified by that object's methods. Otherwise you would have to make the state public and lose encapsulation.
If object A needs to call a method of object B, it needs a reference of B. How else should the method be called.
But what's more important: You seem to assume that OOP is all about modifying objects' state. Unfortunately this impression is given by many introductions. But it is not true. Mutable state causes lots of issues, making programs harder to read and to test. Fortunately most of what you probably need can be done with immutable objects. Just google for immutability. I also recommend to have a look at functional programming where immutability is standard.
(I won't answer your last question because it is off-topic here.)
Currently I am trying my best programming a little video game in the style of the old Zelda games. However, I am having some trouble with the whole OOP style of thinking. To be more specific, I don't really know how to "design" the screens.
Let's say I have a class for my sprites and loaded a Wall-sprite to have a border for a certain area, should I make an extra "wall"-class, or is the wall being a "sprite" already enough? I thought it might be senseless to define an extra class since it would not have any different variables than the actual sprite class (as my wall IS only a sprite) so I didn't consider it to be a useful idea.
I am asking this because I have a little problem with the collision detection as well: What I currently do is loading a sprite for an object only once and rendering it multiple times at several locations. But the problem is that this causes the collision only to be detected at the last position the sprite was rendered at.
It gives me more problems when I render 2 cave-entrances somewhere but my game only checks for the 2nd entrance if I "entered" it.
So I thought making an extra "entrance"-class and creating 2 completely different objects of it that are treated separately might help, but should I then also create 30 objects for my wall-sprites?
Hmmm, there is really two questions, well three, but the OOP-thinking is too non-specific for a good question. So let's see if we can answer it by answering your valid ones.
Good OO Design is centered around "Patterns" (Common solutions to a variety of Problems) in the case of your sprite re-use in OO this would be known as a "Fly-weight" Pattern. Three important structural elements in good OO and understanding them is key to "getting it". They are:
Interfaces - They are free (relatively) of operational code, and provide only method and constructor signatures(generally) to allow for clean separation of coding concerns.
Classes - Only the reusable parts(ideally) of an object they are "the Mold or Pattern" that objects are instantiated (or patterned) from.
Objects - Instances (this chair or that chair as opposed, to Chair as an ideal) of the same form of Class (the ideal Chair). Objects (ideally) should keep as instance values only that which differentiates it from other instances of the same ideal.
However, because your original sprite is not an object you are having this collision problem, because it actually is the same instance rendered again and again, the graphics pipeline does not keep all of its previous locations as separate things it actual just stores pixels(usually), once they've been translated.
In this case if each instance is an object, each instance would have its location as a local instance variable(s), while its graphical representation and collision detection method would be common to all instances of the class.
Don't think of it as having 30 whole copies in memory at once, you only have thirty copies of the instance variables. This is true if you use OO or not; in a procedural solution to get proper collision detection you would have to maintain an array of all of the places you rendered that sprite and iterate through each time, further your code would be less cleanly separated and you would have to iterate through the array for every sprite interaction as well as for updating moving sprites. With OO you could handle this with one class method call that recurses it children.
A good class structure for this simple example might be:
An Abstract Sprite Class (abstract because you will never use a non-specific Sprite) containing only code common to all sprites
A Concrete Wall Sprite Class that extends Sprite, only the code for non-moving wall sprites.
A Concrete Trigger Sprite Class (whose graphic might be clear or null) for behaviors that need to be triggered in "open spaces"
A Concrete Agent Sprite Class for moving sprites (might implement a movable interface meaning all derivatives of the class have a move() method.
A Concrete Character class that extends agent for a movable sprite that is driven by user commands.
It may seem confusing at first, but it's actually cleaner, simpler, and more maintainable doing it the OO way.
:)
I am reading Head First Object Oriented Design to get a better understanding of OOP concepts.
Polymorphism is explained as:
Airplane plane = new Airplane();
Airplane plane = new Jet();
Airplane plane = new Rocket();
You can write code that works on the superclass, like an airplane, but will work with any of the subclasses. :- * Hmmm.. ..I got this one.*.
It further explains:
-> So how does polymorphism makes code flexible?
Well, if you need new functionality, you could write a new subclass of
AirPlane. But since your code uses the superclass, your new class will work
without any changes to the rest of your code.
Now I am not getting it. I need to create a sublass of an airplane. For example: I create a class, Randomflyer. To use it I will have to create its object. So I will use:
Airplane plane = new Randomflyer();
I am not getting it. Even I would have created an object of a subclasses directly. Still I don't see a need to change my code anywhere when I will add a new subclass. How does using a superclass save me from making extra changes to the rest of my code?
Say you have the following (simplified):
Airplane plane = new MyAirplane();
Then you do all sorts of things with it:
List<Airplane> formation = ...
// superclass is important especially if working with collections
formation.add(plane);
// ...
plane.flyStraight();
plane.crashTest();
// ... insert some other thousand lines of code that use plane
Thing is. When you suddenly decide to change your plane to
Airplane plane = new PterdodactylSuperJet();
all your other code I wrote above will just work (differently, of course) because the other code relies on the interface (read:public methods) provided by the general Airplane class, and not from the actual implementation you provide at the beginning. In this way, you can pass on different implementations without altering your other code.
If you hadn't used an Airplane superclass and just written MyAirplane and PterdodactylSuperJet in the sense that you replace
MyAriplane plane = new MyAirplane();
with
PterdodactylSuperJet plane = new PterdodactylSuperJet();
then you have a point: the rest of your code may still work. But that just happens to work, because you wrote the same interface (public methods) in both classes, on purpose. Should you (or some other dev) change the interface in one class, moving back and forth between airplane classes will render your code unusable.
Edit
By on purpose I mean that you specifically implement methods with the same signatures in both MyAirplane and PterodactylSuperJet in order for your code to run correctly with both. If you or someone else change the interface of one class, your flexibility is broken.
Example. Say you don't have the Airplane superclass and another unsuspecting dev modifies the method
public void flyStraight()
in MyAirplane to
public void flyStraight (int speed)
and assume your plane variable is of type MyAirplane. Then the big code would need some modifications; assume that's needed anyway. Thing is, if you move back to a PterodactylSuperJet (e.g. to test it, compare it, a plethora of reasons), your code won't run. Whygodwhy. Because you need to provide PterodactylSuperJet with the method flyStraight(int speed) you didn't write. You can do that, you can repair, that's alright.
That's an easy scenario. But what if
This problem bites you in the ass a year after the innocent modification? You might even forget why you did that in the first place.
Not one, but a ton of modificatios had occurred that you can't keep track of? Even if you can keep track, you need to get the new class up to speed. Almost never easy and definitely never pleasant.
Instead of two plane classes you have a hundred?
Any linear (or not) combination of the above?
If you had written an Airplane superclass and made each subclass override its relevant methods, then by changing flyStraight() to flyStraight(int) in Airplane you would be compelled to adapt all subclasses accordingly, thus keeping consistency. Flexibility will therefore not be altered.
End edit
That's why a superclass stays as some kind of "daddy" in the sense that if someone modifies its interface, all subclasses will follow, hence your code will be more flexible.
A very simple use-case to demonstrate the benefit of polymorphism is batch processing of a list of objects without really bothering about its type (i.e. delegating this responsibility to each concrete type). This helps performing abstract operations consistently on a collection of objects.
Let's say you want to implement a simulated flight program, where you would want to fly each and every type of plane that's present in your list. You simply call
for (AirPlane p : airPlanes) {
p.fly();
}
Each plane knows how to fly itself and you don't need to bother about the type of the planes while making this call. This uniformity in the behaviour of the objects is what polymorphism gives you.
Other people have more fully addressed your questions about polymorphism in general, but I want to respond to one specific piece:
I am not getting it, even I would have create an object of subclasses
directly.
This is actually a big deal, and people go to a lot of effort to avoid doing this. If you crack open something like the Gang of Four, there are a bunch of patterns dedicated to avoiding just this issue.
The main approach is called the Factory pattern. That looks something like this:
AirplaneFactory factory = new AirplaneFactory();
Airplane planeOne = factory.buildAirplane();
Airplane planeTwo = factory.buildJet();
Airplane planeThree = factory.buildRocket();
This gives you more flexibility by abstracting away the instantiation of the object. You might imagine a situation like this: your company starts off primarily building Jets, so your factory has a buildDefault() method that looks like:
public Airplane buildDefault() {
return new Jet();
}
One day, your boss comes up to you and tells you that the business has changed. What people really want these days are Rockets -- Jets are a thing of the past.
Without the AirplaneFactory, you'd have to go through your code and replace possibly dozens of calls to new Jet() with new Rocket(). With the Factory pattern, you can just make a change like:
public Airplane buildDefault() {
return new Rocket();
}
and so the scope of the change is dramatically reduced. And since you've been coding to the interface Airplane rather than the concrete type Jet or Rocket, this is the only change you need to make.
Suppose you have methods in your Controller class of Planes like
parkPlane(Airplane plane)
and
servicePlane(Airplane plane)
implemented in your program. It will not BREAK your code.
I mean, it need not to change as long as it accepts arguments as AirPlane.
Because it will accept any Airplane despite of actual type, flyer, highflyr, fighter, etc.
Also, in a collection:
List<Airplane> plane; // Will take all your planes.
The following example will clear your understanding.
interface Airplane{
parkPlane();
servicePlane();
}
Now your have a fighter plane that implements it, so
public class Fighter implements Airplane {
public void parkPlane(){
// Specific implementations for fighter plane to park
}
public void servicePlane(){
// Specific implementatoins for fighter plane to service.
}
}
The same thing for HighFlyer and other clasess:
public class HighFlyer implements Airplane {
public void parkPlane(){
// Specific implementations for HighFlyer plane to park
}
public void servicePlane(){
// specific implementatoins for HighFlyer plane to service.
}
}
Now think your controller classes using AirPlane several times,
Suppose your Controller class is AirPort like below,
public Class AirPort{
AirPlane plane;
public AirPlane getAirPlane() {
return airPlane;
}
public void setAirPlane(AirPlane airPlane) {
this.airPlane = airPlane;
}
}
here magic comes as Polymorphism makes your code more flexible because,
you may make your new AirPlane type instances as many as you want and you are not changing
code of AirPort class.
you can set AirPlane instance as you like (Thats called dependency Intection too)..
JumboJetPlane // implementing AirPlane interface.
AirBus // implementing AirPlane interface.
Now think of If you create new type of plane, or you remove any type of Plane does it make difference to your AirPort?
No, Because we can say the The AirPort class refers the AirPlane polymorphically.
As far as I understand, the advantage is that, for example, in a airplane combat game, you have to update all airplanes' positions at every loop, but you have several different airplanes. Let's say you have:
MiG-21
Waco 10
Mitsubishi Zero
Eclipse 500
Mirage
You don't want to have to update their movements and positions in separate like this:
Mig21 mig = new Mig21();
mig.move();
Waco waco = new Waco();
waco.move();
Mitsubishi mit = new Mitsubishi();
mit.move();
...
You want to have a superclass that can take any of this subclasses (Airplane) and update all in a loop:
airplaneList.append(new Mig21());
airplaneList.append(new Waco());
airplaneList.append(new Mitsubishi());
...
for(Airplane airplane : airplanesList)
airplane.move()
This makes your code a lot simpler.
You are completely correct that sub-classes are only useful to those who instantiate them. This was summed up well by Rich Hickey:
...any new class is itself an island; unusable by any existing code written by anyone, anywhere. So consider throwing the baby out with the bath water.
It is still possible to use an object which has been instantiated somewhere else. As a trivial example of this, any method which accepts an argument of type "Object" will probably be given an instance of a sub-class.
There is another problem though, which is much more subtle. In general a sub-class (like Jet) will not work in place of a parent class (like Airplane). Assuming that sub-classes are interchangable with parent classes is the cause of a huge number of bugs.
This property of interchangability is known as the Liskov Substitution Principle, and was originally formulated as:
Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.
In the context of your example, T is the Airplane class, S is the Jet class, x are the Airplane instances and y are the Jet instances.
The "properties" q are the the results of the instances' methods, the contents of their properties, the results of passing them to other operators or methods, etc. We can think of "provable" as meaning "observable"; ie. it doesn't matter if two objects are implemented differently, if there is no difference in their results. Likewise it doesn't matter if two objects will behave differently after an infinite loop, since that code can never be reached.
Defining Jet as a sub-class of Airplane is a trivial matter of syntax: Jet's declaration must contain the extends Airplane tokens and there mustn't be a final token in the declaration of Airplane. It is trivial for the compiler to check that objects obey the rules of sub-classing. However, this doesn't tell us whether Jet is a sub-type of Airplane; ie. whether a Jet can be used in place of an Airplane. Java will allow it, but that doesn't mean it will work.
One way we can make Jet a sub-type of Airplane is to have Jet be an empty class; all of its behaviour comes from Airplane. However, even this trivial solution is problematic: an Airplane and a trivial Jet will behave differently when passed to the instanceof operator. Hence we need to inspect all of the code which uses Airplane to make sure that there are no instanceof calls. Of course, this goes completely against the ideas of encapsulation and modularity; there's no way we can inspect code which may not even exist yet!
Normally we want to sub-class in order to do something differently to the superclass. In this case, we have to make sure that none of these differences is observable to any code using Airplane. This is even more difficult than syntactically checking for instanceof; we need to know what all of that code does.
That's impossible due to Rice's Theorem, hence there's no way to check sub-typing automatically, and hence the amount of bugs it causes.
For these reasons, many see sub-class polymorphism as an anti-pattern. There are other forms of polymorphism which don't suffer these problems though, for example "parameteric polymorphism" (referred to as "generics" in Java).
Liskov Substitution Principle
Comparison between sub-classing and sub-typing
Parameteric polymorphism
Arguments against sub-classing
Rice's theorem
One good example of when polymorphism is useful:
Let us say you have abstract class Animal, which defines methods and such common to all animals, such as makeNoise()
You then could extend it with subclasses such as Dog, Cat, Tiger.
Each of these animals overrides the methods of the abstract class, such as makeNoise(), to make these behaviors specific to their class. This is good because obiously each animal makes a different noise.
Here is one example where polymorphism is a great thing: collections.
Lets say I have an ArrayList<Animal> animals, and it is full of several different animals.
Polymorphism makes this code possible:
for(Animal a: animals)
{
a.makeNoise();
}
Because we know that each subclass has a makeNoise() method, we can trust that this will cause each animal object to call their specific version of makeNoise()
(e.g. the dog barks, the cat meows, the cow moos, all without you ever even having to worry about which animal does what.)
Another advantage is apparent when working with a team on a project. Let's say another developer added several new animals without ever telling you, and you have a collection of animals which now has some of these new animal types (which you dont even know exist!). You can still call the makeNoise() method (or any other method in the animal superclass) and trust that each type of animal will know what to do.
The nice thing about this animal superclass is that you can a extend a superclass and make as many new animal types as you want, without changing ANYTHING in the superclass, or breaking any code.
Remember the golden rule of polymorphism. You can use a subclass anywhere a superclass type object is expected.
For example:
Animal animal = new Dog;
It takes a while to learn to think polymorphically, but once you learn your code will improve a lot.
Polymorphism stems from inheritance. The whole idea is that you have a general base class and more specific derived classes. You can then write code that works with the base class... and polymorphims makes your code not only work with the base class, but all derived classes.
If you decide to have your super class have a method, say getPlaneEngineType(), and you make a new child class "Jet which inherits from Plane". Plane jet = new Jet() will/can still access the superclass's getPlaneEngineType. While you could still write your own getJetEngineType() to basically override the superclass's method with a super call, This means you can write code that will work with ANY "plane", not just with Plane or Jet or BigFlyer.
I don't think that's a good example, since it appears to confuse ontology and polymorphism.
You have to ask yourself, what aspect of the behaviour of a 'Jet' is different from an 'Airplane' that would justify complicating the software to model it with a different sub-type? The book's preview cuts off after one page into the example, but there doesn't seem any rationale to the design. Always ask yourself if there is a difference in behaviour rather than just adding classes to categorise things - usually that's better done with a property value or composing strategies than with sub-classes.
An example (simplified from a major project I lead in the early noughties) would be that an Aeroplane is final but has various properties of abstract types, one of which is the engine. There are various ways of calculating the thrust and fuel use of an engine - for fast jets bi-cubic interpolation table of values of thrust and fuel rate against Mach and throttle (and pressure and humidity sometimes), for Rockets the table method but does not require compensation for stalling the air at the engine intake; for props a simpler parametrised 'bootstrap' equation can be used. So you would have three classes of AbstractAeroEngine - JetEngine, RocketEngine and BootstrapEngine which would have implementations of methods which returned thrust and fuel use rate given a throttle setting and the current Mach number. (you should almost never sub-type a non-abstract type)
Note that the differences between the types of AbstractAeroEngine, although related to the different real world engines, are entirely differences in the how the software calculates the engine's thrust and fuel use - you are not constructing an ontology of classes which describe a view of the real world, but specialising the operations performed in the software to suit specific use cases.
How does using a superclass save me from making extra changes to rest of my code?
As all your engine calculations are polymorphic, it means that when you create an aeroplane, you can bolt on whatever engine thrust calculation suits it. If you find you have to cater for another method of calculating the thrust (as we did, several times) then you can add another sub-type of AeroEngine - as long as the implementation it supplies provides the trust and fuel rate, then the rest of the system doesn't care about the internal differences - the AeroPlane class will still ask its engine for the thrust. The aeroplane only cares that it has an engine which it can use the same way as any other engine, only the creation code has to know the type of the engine to bolt onto it, and the implementation of ScramJetEngine only cares about supersonic jet calculations - the parts of AeroPlane which calculate lift and drag, and the strategy for flying it don't have to change.
Polymorphism is powerful given that when there's a need to change a behavior you can change it by overriding a method.
Your superclass inherits its properties and behaviors to your subclasses extended by it. Thus it is safe to implicitly cast an object whose type is also from its superclass. Those common methods to your subclasses make them useful to implement an API. With that, polymorphism gives you the ability to extend a functionality of your code.
Polymorphism gains properties and all behaviors and interfaces of the super class. So is the behavior of a plane really the same as a jet?
This is sort of a methodology question.
When writing software that makes use of object-oriented libraries to abstract OpenGL and the like, should you (or would you) choose to extend the OpenGL helper objects and add your own business logic onto them, or create your basic business objects and then have the OpenGL helpers as a property of them.
For example
Let's say I have an OpenGL library that provides a class
OpenGLBillboard
which draws a 2D sprite that faces the camera
if I have some sort of business object that is going to be rendered using that class, is it wise to simply extend OpenGLBillboard and build on top of it, or should I just have an OpenGLBillboard object that is a property on what is essentially a base class in my software?
It seems like inheritance in this case could be dangerous because if the base class ever has to change due to requirements, the refactoring could be painful ... whereas if I just go the property route, I have a little more upfront boilerplate to write.
Your thoughts?
Thanks
P.S. forgive me for saying "business object". I just didn't want to say "model" a whole lot in a topic about 3D and have people be confused as to my meaning.
Personally, I would probably have my business object contain (privately) a "Billboard" instance, and not tie it directly to OpenGL at all.
The business object would just be asked to render, and redirect it's methods through the Billboard instance. This would allow you to swap out a different implementation (if you decide to go with something other than a Billboard) or a different backend (ie: a Direct3D rendering pipeline) without changing the business object at all.