Reading "Thinking in Java" by Bruce Eckel at the moment. Reached "this" keyword point. It's not clear for me how really objects and "this" work. Bruce Eckel in his book says:
If you have two objects of the same type called a and b, you might wonder how it is that you can call a method peel( ) for both those objects:
//: initialization/BananaPeel.java
class Banana { void peel(int i) { /* ... */ } }
public class BananaPeel {
public static void main(String[] args) {
Banana a = new Banana(),
b = new Banana();
a.peel(1);
b.peel(2);
}
} ///:~
If there’s only one method called peel( ), how can that method know whether it’s being called for the object a or b?
To allow you to write the code in a convenient object-oriented syntax in which you “send a message to an object,” the compiler does some undercover work for you. There’s a secret first argument passed to the method peel( ), and that argument is the reference to the object that’s being manipulated. So the two method calls become something like:
Banana.peel(a, 1);
Banana.peel(b, 2);
So, when we create an object it has it own methods copied from the class.
A obj = new A();
obj.callMethod(); //<-- object uses it's own method, not the class, right?
And according to the book the methods of a class are shared somehow between all
the objects created from this class.
How does this mechanism work in the result?
I don’t get this part:
If you have two objects of the same type called a and b, you might wonder how it is that you can call a method peel( ) for both those objects.
If there’s only one method called peel( ), how can that method know whether it’s being called for the object a or b?
What does it mean “only one method called peel()”
We have all the methods from the class created for each object. So we just call the method from the object.
What did Bruce Eckel mean?
If you and I both laugh when something is funny, you may say that we share the ability to laugh.
I am thinking of sharing methods between instances of a class in much the same way. Bananas share the property that they can be peeled. The Banana class specifies what Banana objects are and what they can do. Some have described the class as a template for creating objects or a rubber stamp for stamping them. All bananas can be peeled, but the programmer still decides which ones s/he actually peels, and when. In programming terms: The Banana class specifies that every banana has a peel method, and what that method is.
When Eckel does a.peel(1); he’s specifying that he is peeling banana a (and not banana b just yet). As far as I am concerned, this all you as an object-oriented programmer need to know to use bananas and their methods.
Classes, objects and instance methods are described in many ways in many places. You may see if it helps you to search for other descriptions to supplement the one by Eckel.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 25 days ago.
Improve this question
Here's an example taken from their site:
An example of Polymorphism in Java
Difference between Polymorphism, Overloading and Overriding in Java with ExampleLet's see a short example of Polymorphism in Java. In this example, the Pet variable behaves polymorphically because it can be either Cat or Dog. this is also an example of method overriding because the makeSound() method is overridden in subclass Dog and Cat.
import java.util.ArrayList;
import java.util.List;
abstract class Pet{
public abstract void makeSound();
}
class Cat extends Pet{
#Override
public void makeSound() {
System.out.println("Meow");
}
}
class Dog extends Pet{
#Override
public void makeSound() {
System.out.println("Woof");
}
}
Let's test How the Polymorphism concept works in Java:
/**
*
* Java program to demonstrate What is Polymorphism
* #author Javin Paul
*/
public class PolymorphismDemo{
public static void main(String args[]) {
//Now Pet will show How Polymorphism work in Java
List<Pet> pets = new ArrayList<Pet>();
pets.add(new Cat());
pets.add(new Dog());
//pet variable which is type of Pet behave different based
//upon whether pet is Cat or Dog
for(Pet pet : pets){
pet.makeSound();
}
}
}
Output:
Meow
Woof
In Summary, you can not compare Polymorphism with method overloading or override. Polymorphism is the ability of a variable to behave differently based upon which kind of Object it is referring to. They are Java programming language's way to implement polymorphism in language.
In the second example is the author just trying to make the point that at runtime we don't know what the objects are going to be? but this also includes an example of overriding?
Read more: https://www.java67.com/2012/10/difference-between-polymorphism-overloading-overriding-java.html#ixzz7rRlx0PQY
So is this a form of overriding or not?
A term is a way to ease communication. My brain thinks of a notion and I wish to convey it to your brain. My brain comes up with some words that encompass the notion I am trying to convey. I make my mouth move and my voicebox, shaking air comes out, they reach your ears, from there to your brain, and from there you decode the audio message.
The communication is succesful if the notion you think I'm trying to convey is roughly equivalent to what I was actually trying to convey.
And that is all that these terms are good for.
It's clear that you're just hopelessly confused (this isn't the first question you're asking about it). Why do you 'care'? You do not need to know what the word 'override' is supposed to mean, you merely need to know the concept and the rules as the JVM / javac applies them. You can all this 'overriding', or you can call it 'floobargling' for all I care. As long as it is clear to you.
If you don't even understand what the book is trying to tell you about these concepts, then 'let me try to ask some java programmers what they think this term means, and then if they think this java language feature is an application of what they think this term means' isn't going to get you any closer to understanding it.
Specifically, 'polymorphism' is useless here. It's a nebulous term that people use to describe orthogonal concepts. In the job of conveying notions from brain to voice (or keyboard, if you prefer) to ears to another brain, summarizing notions by using the term 'polymorphism' is likely going to lead to failure to communicate.
Override and Overload on the other hand are much better defined: These terms explicitly used in the Java Language Specification to mean very specific things in the context of java. Whether you feel these are 'forms' or 'examples' of polymorphism depends entirely on what you feel the term means. I don't see why it is relevant to know. Possibly you have some understanding of the notion of having the same code do different things depending on what you provide as input to this code, and that this is 'polymorphism', and you are trying to figure out what java's concepts of 'overload' and 'override' mean, in which case I suggest you just.. learn what those terms mean. Instead of praying that you ask somebody if these are 'forms of polymorphism' and that they have the same understanding of what polymorphism means as you do.
Or perhaps this is some sort of homework exercise where you need to write an essay about it all, in which case, the advice is mostly the same. Try to understand the concepts, don't worry so much about what terms to use.
overriding
In java, for methods only (not constructors, not fields), any type can define an entirely new method. A method has an 'identity' and that identity is defined by both its name as well as all its parameter types, and at least at the class file level, even its return type. In contrast, if you define a method whose identity matches exactly with a method identity from a class or interface that is a supertype, then you aren't defined a new method, you are overriding the method from the supertype. At the language level (so, what javac does), a tightened return type is still an override (but that doesn't count for parameter types), and generics do not factor into this at all (because at the runtime level, i.e. class files and java.exe, generics do not exist). So:
class Parent {
Object foo(String a) {
System.out.println("In parent");
return null;
}
}
class Child extends Parent {
String foo(String b) {
// This is an override
System.out.println("In child");
return null;
}
}
Java does 'dynamic dispatch', meaning: Whenever you invoke a method, the most specific override available is actually invoked. It's about the actual type of the object that is referred to by your expression, and not about the expression's type. Thus:
Parent p = new Child();
p.foo("");
prints "In child". Even though the type of p is parent, if you follow the pointer, p turns out to actually be pointing at an instance of Child, and Child's foo() impl is more specific. And therefore, is used. You can't tell java not to do this - only Child itself could (by invoking super.foo(a) to explicitly invoke the parent's implementation of foo(). You can't do something like p.super.foo(""), that isn't legal java.
Overloading
As I mentioned, the identity of a method includes its parameter types. Thus, given:
class Parent {
void foo(String a) {
System.out.println("in Parent");
}
}
class Child extends Parent {
void foo(Object b) {
System.out.println("in Child");
}
}
These are completely different methods. As different as a method named 'jane' and another method named 'aubrey' - utterly, completely unrelated.
Parent p = new Child();
p.foo(null);
That would compile and print 'In Parent'. Because given that p is of type Parent, the only foo method that foo(null) could possibly be referring to, is the foo(String) method that is in Parent, so that is invoked. At runtime the system dutifully goes looking for the most specific implementation of it, which is Parent's foo - because the foo in child is a completely different method. After all, its identity doesn't match.
If you tried this:
Child c = new Child();
c.foo(null);
There are 2 completely different methods but either one could feasibly be called. Javac will refuse to compile it and tell you this is an ambiguous method invocation (javac isn't clear which one you wanted). The key difference is that in this second example, there are 2 different methods, whereas in the first (where we are overriding), there is only one method identity, and 2 implementations of that identity.
Given that these are 2 different methods, it's the compiler that needs to translate p.foo() into a class file, and as part of that job, it needs to name the full method identity of what you are attempting to invoke: Javac figures out which of a bunch of overloads you meant to call.
So, which one is polymorphism?
That depends entirely on what you mean by 'polymorphism'. The java lang spec doesn't use that word, a java programmer therefore doesn't need to care about that word. The first example is overriding. The second is overloading. I don't see what the point is of bringing a nebulous, ill-defined term in the mix.
This question already has answers here:
Can I override and overload static methods in Java?
(19 answers)
Closed 5 months ago.
Would it be correct to say that static methods in a class extended with a class, in an interface extended with an interface and in an interface implemented by a class can only be redeclared in the extending/implementing part (hiding the original method in the class extending class case), and any other method can only be overridden there? And is redefining the same as overriding?
If not, can someone please explain these concepts with a flowchart (I've looked at other explanations and they don't give me the overview I'm looking for)?
Would it be correct to say that static methods in a class extended
No. static methods fundamentally are un-inheritable, and un-overridable. Or rather, conceptually it just doesn't apply.
Saying: "This static method is an override" is a bit like stating: "This smells blue" - it's not clear what that would even mean.
overriding is relevant essentially only for the notion of dynamic dispatch. Dynamic dispatch is this idea:
class Dog {
void bark() { System.out.println("Woof"); }
}
class Bulldog extends Dog {
void bark() { System.out.println("Grrrr"); }
}
Dog d = new Bulldog();
d.bark(); // prints "Grrrr"
That's dynamic dispatch at work. d is a variable. Like all non-primitives in java, it is a reference. Meaning, values stored in this variable are the reference - a pointer. An address in an addressbook that lets you get to a house, not the house itself. d's type is Dog. Its value is a reference to an actual instance of some object (and java guarantees that whatever the actual type it is an instance of, that type is Dog or a subtype of Dog). That reference gets you an instance of Bulldog. So, when invoking bark() here, what happens?
Dynamic dispatch: Java finds the most specific implementation of this method, and calls that. So that prints Grrrr, and not Woof.
However, when talking about static methods, the entire concept doesn't apply. Dynamic dispatch occurs because there is a discrepancy between the type of the reference (which is Dog here, that's the type of variable d) and the type of the thing the reference is pointing at (which is Bulldog). Overriding as a concept exists because these 2 types may not be the same.
When invoking static methods, this doesn't come up. You always write SomeType.someStaticMethod(), so what would dynamic dispatch even be?
SIDENOTE: You can legally invoke static methods using an expression. This is legal:
List.of("a", "b"); // this is how you normally do it
List<Integer> list = new ArrayList<Integer>();
list.of("a", "b"); // this compiles and works
But make no mistake - the compiler treats it the same and cares only about the type of list, not about the object the variable is pointing at. In fact, list = null; list.of("a", "b"); works fine, no NullPointerException, proving the point that list doesn't get dereferenced when you do this. All style guides strongly recommend not doing this, for good reason.
SIDENOTE 2: Unfortunately java lets you declare a static method as final which is weird: final means: Cannot be overridden, and we just figured out that 'override' conceptually doesn't make sense for static methods. It's just what it is - it's a design error in the original java spec and java does not like making changes that break existing code unless there is an incredibly good reason to do so, and whilst this spec brainfart is annoying, it doesn't hurt much. Just don't declare your static methods final. It even adds a rule (subtypes cannot declare a static method with the same signature) which is even more bizarre. Again, disregard that - java spec error that doesn't get fixed because not worth the headache.
And is redefining the same as overriding?
Yes. 2 words for the same thing. The correct term is 'override' - both the java lang spec uses this term, and the vast majority of the community does. If I was an editor of whatever tutorial, blogpost, documentation, or presentation you got this 'redefine' term from, I'd edit it. Unless the author was specifically talking about this:
class Parent {
static void foo() {}
}
class Child extends Parent {
static void foo() {}
}
In which case 'override' is the wrong term to use (given that static methods and override are orthogonal concepts), though I wouldn't use 'redefine' either. You're just defining a method named foo in one class, and also defining a method named foo in another. The fact that one is a child of the other is irrelevant; both have a foo method now. The foo method in child does not override or redefine anything; there's no such thing in static world.
with a flowchart
A flowchart requires some sort of flow to chart. Hence the name. No such thing here.
I am studying up on my Java Programming and Object Oriented Programming. I keep getting hung up on what the benefit of Dynamic Polymorphism is?
Take a look at my sample program below.
Why would I use example 1 over example 2?
class SuperHero {
private String power = ("Generic Power");
public void useSuperPower() {
System.out.println(power);
}
}
class Spiderman extends SuperHero {
private String power = ("Web sling!");
public void useSuperPower() {
System.out.println(power);
}
}
class Wolverine extends SuperHero {
private String power = ("Hack and Slash!");
public void useSuperPower() {
System.out.println(power);
}
}
class main {
public static void main (String args[]) {
//example 1
SuperHero hero = new SuperHero();
SuperHero hero1 = new Spiderman();
SuperHero hero2 = new Wolverine();
hero.useSuperPower();
hero1.useSuperPower();
hero2.useSuperPower();
//example 2
Spiderman test = new Spiderman();
Wolverine test2 = new Wolverine();
test.useSuperPower();
test2.useSuperPower();
}
}
The easiest example of when dynamic polymorphism is powerful is in collections. We can collect objects of different classes together, and use them all the same, so long as they all share a single parent interface. For instance:
List<SuperHero> avengers = new ArrayList<>();
avengers.add(new Spiderman());
avengers.add(new Wolverine());
System.out.println("Avengers Assemble!");
for(SuperHero hero : avengers){
hero.useSuperPower();
}
It also allows for APIs to be very flexible. We can create methods which expect one interface, but later on pass them an object of a child type, without having to recreate that method. For instance:
public void usePower(SuperHero hero){
hero.useSuperPower();
}
Here, we can call this method with object which extends SuperHero. (That example is a bit lame, since we could just call the useSuperPower() method directly, but hopefully you get the point.)
Basically, polymorphism allows us to create classes which all do the same thing, but do it differently, and then use them (almost) interchangeably.
You'll probably never use example 1 directly. HOWEVER, you may end up in example 1 anyways (and hence Dynamic Polymorphism has value).
Let's say the two of us are coding a game together, and you've written the superhero hirearchy as you have in the question. Over on my side, I've written a class called JusticeLeagueScheduler with the method:
public JusticeLeagueScheduler {
public static Superhero getAvaiableHero() {
// ...
}
}
Which allows you to get access to a superhero who can help save the day. Furthermore, suppose that the method getAvailableHero() is absurdly long, as it needs to take into account how often each superhero has been used, Logan's current BAC, Peter Parker's school schedule, etc etc etc.
When you call that method, you'll do so like this:
SuperHero superhero = JusticeLeagueScheduler.getAvailableHero();
At this point, you have no idea which hero you have, only that it is an instance or subclass of class SuperHero. Thus, you are in the situation in example 1. You can't call Wolverine methods on superhero, because it might be Wolverine, but it also might not be. You can call only methods defined by class SuperHero (or its parent type Object) on superhero.
However, it will still be the instance it is. If my method returns a Wolverine instance to you, and you call userSuperPower(), you will get "Hack and Slash", even though you couldn't have predicted that beforehand.
In example 1, hero, hero1 and hero2 are all of type SuperHero. When you use the same method on different SuperHero objects, they behave in different manner. That is polymorphism.
However, in example 2, hero, hero1 and hero2 are all of different types. So, the example doesn't demonstrate polymorphism.
Yes, you are saving yourself time and saving yourself code.
Polymorphism in Java
Polymorphism in java is a concept by which we can perform a single
action by different ways. Polymorphism is derived from 2 greek words:
poly and morphs. The word "poly" means many and "morphs" means forms.
So polymorphism means many forms.
There are two types of polymorphism in java: compile time polymorphism
and runtime polymorphism. We can perform polymorphism in java by
method overloading and method overriding.
If you overload static method in java, it is the example of compile
time polymorphism. Here, we will focus on runtime polymorphism in
java.
Runtime Polymorphism in Java
Runtime polymorphism or Dynamic Method Dispatch is a process in which
a call to an overridden method is resolved at runtime rather than
compile-time.
In this process, an overridden method is called through the reference
variable of a superclass. The determination of the method to be called
is based on the object being referred to by the reference variable.
Let's first understand the upcasting before Runtime Polymorphism.
Now let's take an example where you will need to convert one Spiderman object to SuperHero class, would you be able to do so if you instantiate without dynamic polymorphism. Answer is no.
Read more about Collection API and you will know why we need Dynamic Polymorphism.
Read this answer to understand the concept.
So, if you do the following:
SuperHero hero1 = new Spiderman();
SuperHero hero2 = new Wolverine();
You can also do:
SuperHero hero3 = new Spiderman();
hero3 =(Superhero) hero2;
Which you won't be able to do if you don't apply polymorphism.
if a Fruit class is superClass and Apple and Orange are subclasses of Fruit,
and GoldenDelicious and Macintosh are sub classes of Apple.
Assume that the following declaration is given:
Fruit fruit = new GoldenDelicious();
Orange orange = new Orange();
Answer this question with explain
Suppose the method makeAppleCider is defined in the Apple class. Can
fruit invoke this method? Can orange invoke this method???
My answer is : Can
fruit invoke this method? No beacuse there aren't explicit cast , must do explicit cast of
fruit instance to enable invoke the method defined in Apple class. dose this answer is true ????
This dives into the static and dynamic types of a variable.
Fruit fruit;
This line declares a variable fruit with static type Fruit. This type will never change (it's static after all) and is what you will usually be using.
fruit = new GoldenDelicious();
This line is one that assigns a value that is a GoldenDelicious to that variable. The dynamic type of the variable does change to reflect this change. After all, the variable actually contains a GoldenDelicious now. The dynamic type is something you usually won't be working with, but it is what is used when you use the (evil) instanceof (and it makes sure that overwritten function are called in the right place).
Now, you want to do this:
fruit.makeAppleCider();
This will not work. Of fruit, we basically only know the static type, and the static type Fruit knows nothing of that method. (However, behind the scenes, if GoldenDelicious and Macintosh implement the function in different ways, the dynamic type will make sure the right version is called.)
As you mentioned in your answer, explicit casts could be used to change the static type of what you are working with, and as such you could make it work that way. It is better not to do that, though, as casts should be avoided and aren't "proper OOP".
In conclusion, yes, your answer was correct.
(Yes, my description is a bit technical. I hope you'll forgive me for that...)
A Fruit has no "knowledge" of the makeAppleCider method. makeAppleCider is defined in a subclass and is not a member of Fruit. A class only has access to the methods it or one of its parents defines. Given a class of a certain type, you have to trace back up the class hierarchy to see what methods you can access. You can think of the type of your variable as the starting place for the walk back up the class hierarchy.
If there is a method you want all of your classes to have access to, put it in the root of the hierarchy. Obviously, the logic of using the method should make sense or people who use your code will be confused.
The other option, of course, is to use an "interface" -- a sort of poor-man's multiple inheritance (but far easier to understand and implement than full-out multiple inheritance).
You could, eg, have an interface sorta like (not syntax checked):
public interface CiderFruit {
public void makeCider();
}
Then Apple could implement the interface:
public class Apple extends Fruit implements CiderFruit {
....
public void makeCider() {
doStuff();
}
....
}
If you then had a Quince class it could implement the same interface and one could take either an Apple or a Quince, cast it to CiderFruit (if unsure whether it's Apple or Quince), and invoke makeCider(). (One could also invoke directly with a reference typed as Apple or Quince.)
I am facing a continuing problem distinguishing delegation, composition and aggregation from each other, and identifying the cases where it's the best to use one over the other.
I have consulted a Java OO Analysis and Design book, but my confusion still remains. The main explanation is this:
Delegation: When my object uses another object's functionality as is without changing it.
Composition: My object consists of other objects which in turn cannot exist after my object is destroyed-garbage collected.
Aggregation: My object consists of other objects which can live even after my object is destroyed.
Is it possible to have a few simple examples demonstrating each case, and the reasoning behind them? How else can these examples be demonstrated other than my object simply having a reference to another object(s)?
Delegation
public class A {
private B b = new B();
public void methodA() {
b.methodB();
}
}
When clients of A call methodA, class A delegates the call to B's methodB.
Rationale. Class A exposes behaviours that belong elsewhere. This can happen in single-inheritance languages where class A inherits from one class, but its clients need behaviours that are implemented in a different class. Further study.
Hybrid Delegation
public class A {
private B b = new B();
public void methodA() {
b.methodB( this );
}
}
The difference between delegation that involves simple forwarding and delegation that acts as a substitute for inheritance is that the callee must accept a parameter of the caller, exemplified as:
b.methodB( this );
Rationale. Allows class B instances to use functionality available from class A, just as class B would if it inherited from class A--but without inheritance. Further study.
Composition
public class A {
private B b = new B();
public A() {
}
}
Once no more references to a particular instance of class A exist, its instance of class B is destroyed.
Rationale. Allows classes to define behaviours and attributes in a modular fashion. Further study.
Aggregation
public class A {
private B b;
public A( B b ) {
this.b = b;
}
}
public class C {
private B b = new B();
public C() {
A a = new A( this.b );
}
}
Once there are no more references to a particular instance of class A, its instance of class B will not be destroyed. In this example, both A and C must be garbage collected before B will be destroyed.
Rationale. Allows instances to reuse objects. Further study.
Demonstration Without References
The names given to these simple patterns are defined by their referential relationships.
Your object would reference another object(s) in all three cases. The difference lies in behavior and / or lifecycle of referenced objects. Some examples:
Composition: House contains one or more rooms. Room's lifetime is controlled by House as Room will not exist without House.
Aggregation: Toy house built from blocks. You can disassemble it but blocks will remain.
Delegation: Your boss asked you to get him a coffee, you've had an intern do it for you instead. Delegation is not a type of association (like composition / aggregation are). The latter two have been discussed on Stack Overflow many times
In the comment you ask how the implementation would differ in each case, observing that in all cases we invoke methods on the releated objects. It's true that in each case we would have code such as
myRoom.doWork();
myBlock.doWork();
myMinion.doWork();
but the differences lie in the life-cycle and cardinality of the related objects.
For the Component, the Rooms come into existence when the House is created. So we might create them in the constructor of the House.
In the case of Association (I'll use Tyre and Car) Cars might add Tyres in their constructor, but later you may want to remove and change tyres. So you also have methods such as
removeTyre(FrontLeft)
addNewTyre(aTyre, BackRight)
And it's quite likely that the aTyre object came from a Factory - we didn't new it in any of the Car's methods.
In the case of Delegation, you might not even have a member variable to hold the delegate
resourcingPool().getIntern().getCoffee(SkinnyLatte, workstation 7);
the relationship between the objects lasts only as long as the intern is fetching the coffee. Then it returns to the resource pool.
Your book explains quite good so let me elaborate and provide you some examples.
delegation: When my object uses another object's functionality as is without changing it.
Sometime a class may logically need to be big. But big class is not a good coding pratice. Also sometime, some functionalities of a class may be implementable in more than one way and you may want to change that some time.
class FeatureHolder {
void feature() {
// Big implementation of the feature that you dont want to put in the class Big
}
}
class Big {
private FeatureHolder FH = new FeatureHolder();
void feature() {
// Delegate to FeatureHolder.
FH.feature();
}
//.. Other features
}
From the above example, Big.feature() call feature of FH as is without changing it. This way, the class Big does not need to contain the implementation of the feature (separation of labour). Also, feature() can implement differently by other class like "NewFeatureHolder" and Big may choose to use the new feature holder instead.
composition: My object consists of other objects which in turn cannot exist after my object is destryed-garbage collected.
aggregation: My object consists of other objects which can live even after my object is destroyed.
Technially, Composition is "part of" and Aggregation is "refer to" relationship. Your arms are part of you. If you no longer live, your arm will die too. Your cloth is not part of you but you have them; as you can guest, your cloth does not go with you.
In programming, some objects are part of another object and they have no logical meaning without it. For example, a button is composed into a window frame. If a frame is closed, the button has no reason to be around anymore (Composition). A button may have reference to a database (like to refreash data); when the button is eliminated, the database may still be around (Aggregation).
Sorry for my English, Hope this helps
1) Delegation: Man-driver-car example. A Man bought a car. But that man does not know to drive the car. So he will appoint a driver who knows driving a car. So the Man class wants to perform a transportation using car. But it does not have the interacting- functionality/compatibility with car. So he uses a class which has compatibility with car that is driver which is compatible with man class. Assuming that driver can understand what man says
2) Composition: Car simulation is a routine example. To make a car move, wheel rotates. Car class using wheel class rotate functinality as part of its move function, where as wheel is part of car.
3) Aggregation: Car and its colour. Car class object ferrari will have a colour class object red. But colour class object red can be there as individual class, when user search happens with a specification of red colour.
In a very simple sentence I can say:
Delegation is: delegate behaviour to other class when you do not want to change it. by change I mean during run time. for example you delegate driver to car class that driver wont change while driving.
Composition is: when you want to use behaviour of family of classes (one or more classes, that implements an interface) that you might change during run time. but you should consider these classes can not exist with out main classes, such as rooms of a hotel. If you remove hotel all rooms of hotel will not exist.
Aggregation is: same as composition but classes can exist without main class.