I've seen plenty of posts on Stackoverflow explaining the difference between the relationships: associations, aggregation, composition and inheritance, with examples. However, I'm more specifically confused more about the pros and cons of each of these approaches, and when one approach is most effective for the task in hand. This is something I've not been able to really find a good answer on.
Keeping inline with the forum's guidelines, I'm not asking for why people might personally prefer using inheritance over composition, for example. I'm specifically interested in any objective benefits/weaknesses in each approach, as strong as that may sound. I.e. does one approach create more readable code than another, or does it have a better run time efficiency etc.
Ideally, if someone could give me some real world examples where these approaches may have succeeded or failed and why, that would be extremely useful for developing my and, I hope, others knowledge.
In the interest of ensuring a solid base to work off, I've included examples of each relationship in Python 2. Hopefully this should allow confusion to be avoided, if my understanding of these relationships is not in-fact correct.
Association
Class B has a week association relationship with Class A, as it uses specific attributes from A in the addAllNums method. However, that is the extent of the relationship.
class A(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def addNums():
self.b + self.c
class B(object):
def __init__(self, d, e):
self.d = d
self.e = e
def addAllNums(self, Ab, Ac):
x = self.d + self.e + Ab + Ac
return x
ting = A("yo", 2, 6)
ling = B(5, 9)
print ling.addAllNums(ting.b, ting.c)
Aggregation
Class B forms an aggregation relationship with Class A, as it references an independent A object when initialized, as one of its attributes. Whilst a B object is dependent on A, in the event of B's destruction, A will continue to exist as it is independent of B.
class A(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def addNums():
self.b + self.c
class B(object):
def __init__(self, d, e, A):
self.d = d
self.e = e
self.A = A
def addAllNums(self):
x = self.d + self.e + self.A.b + self.A.c
return x
ting = A("yo", 2, 6)
ling = B(5, 9, ting)
print ling.addAllNums()
Composition
Much like aggregation, however rather than referencing an independent object, B actually initializes an instance of A in it's own constructor as an attribute. If the B object is destroyed then so too is the A object. This is why composition is such a strong relationship.
class A(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def addNums():
self.b + self.c
class B(object):
def __init__(self, d, e):
self.d = d
self.e = e
self.A = A("yo", 2, 6)
def addAllNums(self):
x = self.d + self.e + self.A.b + self.A.c
return x
ling = B(5, 9)
print ling.addAllNums()
I've decided not to include an example of inheritance as I'm completely happy with it, and I feel that its inclusion may throw the point of the question off at a bit of a tangent.
Regardless, again, what are the pros and cons of the above examples and inheritance (compared to one another).
Thanks.
The rule of thumb as per wikipedia is that the relationships soften over time, or over the increasing detail of your conceptual model i.e. compositions become aggregations and aggregations become associations, for example an engine may be a composition of a car originally but as you add functionality, the engine could be transferred from one car to another making it an aggregation.
So to answer your question of the pros and cons of each method, it's more a question of the relationship you are modelling, similar to the question should I store a Name as a string or a number