Wikipedia on the diamond problem:
"... the diamond problem is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If a method in D calls a method defined in A (and does not override the method), and B and C have overridden that method differently, then from which class does it inherit: B, or C?"
So the diamond looks like this:
A
/ \
B C
\ /
D
My question is, what happens if there is no such class A, but again B and C declare the same method, say foo(). Isn't this the same problem? Why is it then called diamond problem?
Example:
class B {
public void foo() {...}
}
class C {
public void foo() {...}
}
class D extends B, C {
}
new D().foo();
Its not the same problem.
In the original problem, the overriden method can be called from A. In your problem this can't be the case because it does not exist.
In the diamond problem, the clash happens if class A calls the method Foo. Normally this is no problem. But in class D you can never know which instance of Foo needs to be called:
+--------+
| A |
| Foo |
| Bar |
+--------+
/ \
/ \
/ \
+--------+ +--------+
| B | | C |
| Foo | | Foo |
+--------+ +--------+
\ /
\ /
\ /
+--------+
| D |
| |
+--------+
In your problem, there is no common ancestor that can call the method. On class D there are two flavors of Foo you can chose from, but at least you know that there are two. And you can make a choice between the two.
+--------+ +--------+
| B | | C |
| Foo | | Foo |
+--------+ +--------+
\ /
\ /
\ /
+--------+
| D |
| |
+--------+
But, as always, you do not need multiple inheritance. You can use aggegration and interfaces to solve all these problems.
In the diamond problem, class D implicitly inherits the virtual method from class A. To call it, class D would call:
A::foo()
If both classes B and C override this method, then the problem comes of which actually gets called.
In your second example however, this isn't the case as class D would need to explicitly
state which was being called:
B::foo()
C::foo()
So the problems are not actually the same. In the diamond problem you aren't referencing the derived classes, but their base class, hence the ambiguity.
That's how I understand it, anyway.
Note that I'm coming from a C++ background.
Your second example is nowhere near the diamond problem because compiler has the ability to detect the available functions one level up of inheritance.
Once the compiler gets to know that you are using same-named functions in two base classes, it will throw error: member 'foo' found in multiple base classes of different types.
The diamond problem only arises from incorrect type/ontology modeling. It doesn't exist in properly-modeled systems.
The problem arises usually because developers define classes for entities based on their roles not their types. They elevate what it can do above what it actually is. The entity object carries the role not the type.
A person is a person, for example, from birth to death regardless of whether he gets married (Husband), visits mom (Son), or lands a great job (Employee). The roles for Person can be implemented with interfaces or components or mixins—fuel in the argument to prefer composition to inhertiance.
It would be reasonable to allow an entity's type to be replaced via some state machine transition. Thus, a Person could be replaced with Werewolf (full moon) or Vampire (neck bite) as the result of a state transition. The entity (some fixed GUID) remains regardless of the transition. But even this can be modeled differently—a Person with Lycanthropy and/or Vampirism. Of course, modeling to accommodate many facets can be a challenge, but it it has nothing to do with the typical limitation that classes may participate in a single inheritance chain.
An UnverifiedEmailAddress could transition to a VerifiedEmailAddress, but this is not a great example because it probably ought use a value object rather than a reference object. A better example could involve a WorkingPurchaseOrder transitioning to a SubmittedPurchaseOrder via a submit function. The function would likely return an immutable replacement (such as a Persistent Object) and be swapped into some observable state container.
Related
I have a Interface called Animal which has 5 methods (abstract). Now in my Animal kingdom we have 1000(with 1000 different overridden method ) Animals(CAT,DOG,SNAKE....etc) but creating a 1000 different class for all the animals would be hectic and even when they created managing them would be really difficult , any suggestion would be appreciated.... visual presentation is available below.
Animal(I)(5 Methods)
---------------------------------------
| | | | ----------- |
DOG CAT SNAKE LION TIGER
My main goal is to reduce the number of classes .
NOTE: every animal is overriding one or more different methods and are truly different from each other
I've a class diagram like this:
TopClass
◆ ◆
| |
SubClass1 SubClass2
◆ ◆
| |
| ChildClass2
|
ChildClass1
TopClass has SubClass1 and SubClass2.
Subclass1 has ChildClass1 and ChildClass2.
I use dependency injection on each of these classes. So when ChildClass1 needs interface X I need to pass X thru TopClass and Subclass1. When ChildClass2 needs Y I also need to pass it thru whole hierarchy. Eventually I end up with TopClass full of dependencies to interfaces it actually doesn't use. I find it smelly.
I've found an article about facade pattern which seemd promising but eventually I cannot find a way to use it in my situation.
Any other idea? And I wouldn't like to use singleton or any similar solution as I need to be able to unit tests these classes easily.
EDIT
Another option which I just found and which I'm going to test for a while is boost.DI:
http://boost-experimental.github.io/di/cpp-london-2017
http://boost-experimental.github.io/di/
Let's say I have inheritance like this
Person
|
+-----+------+
| |
Student Teacher
Then I would call Person the Base.
How would I call Student?
Inherited class sounds stupid. Is there a single word for it?
Basically using Base for super class, so: PersonBase
And for it's implementations it's common to add Impl like: StudentImpl and TeacherImpl
In a lecture about Class diagrams the following slide appeared which describes the relationship in an Elevator system:
The lecture called the black headed arrows a "composite aggregation" relationship which means that the child cannot exist independently of the parent.
In this elevator system example, the Motor object is irrelevant outside of the Elevator object.
What I don't understand though is how the composite aggregation appears in the code itself. I'd expect there to be a "myMotor" property in the Elevator but there isn't.
Is it because by drawing this relationship we tell the programmer that he needs to implement it but the implementation details are his to choose?
As opposed to the father object's proprties which are stated explicitly (like the elevator's isActive boolean property)?
U.M.L. can be used, in several ways,as very conceptual design tool, or a more specific programming design tool.
So, when representing a composite aggregation, it can be represented in several ways.
Sometimes, you may want to display all members of a class. Bad, when there are too much members.
+--------------------------+
| ElevatorClass |
+--------------------------+
| [+] boolean: isActive |
| [+] boolean: isInOrder |
| [+] Floor: Location |
| [+] MotorClass: Motor |
| [+] DoorClass: Door |
+--------------------------+
| [+] startOperation() |
| [+] stopOperation() |
| [+] gooUp() |
| [+] gooDown() |
| [+] openDoor() |
| [+] closeDoor() |
+--------------------------+
Sometimes, you may want to hide all members of a class. Good, when you want to focus in the class, not the members. Note: This may be the case you are looking right now.
+--------------------------+1 1+--------------------------+
| ElevatorClass |------<*>| RescueButtonClass |
+--------------------------+ +--------------------------+
Sometimes, you may want to show some members of a class, and hide another.
+--------------------------+ 1 1 +--------------------------+
| ElevatorClass |------<*>| MotorButtonClass |
+--------------------------+ +--------------------------+
| [+] boolean: isActive |
| [+] boolean: isInOrder |
| [+] Floor: Location |
| [+] MotorClass: Motor |
| [+] DoorClass: Door |
+--------------------------+
To make things a little complicated, the motor, as well as the other elements, doesn't necesarilly have to be referenced by a reference member in the elevator class.
Example (c style):
class ElevatorClass {
public:
List<ComponentClass*> Components;
...
void AddComponent(ComponentClass* ThisComponent);
} // class ElevatorClass
...
MyElevator.AddComponent(MyMotor);
In the previous code example, the member is not referenced directly.
Personally I agree with you that this its very clear:
class ElevatorClass {
public:
MotorClass* Motor;
MotorClass* Motor;
} // class ElevatorClass
Cheers.
For a Composite Aggregation (also called Composition), USUALLY this indicates a parent-child relationship. In your example, an Elevator object in your code would contain a reference to only one Motor object. Here is a link to a blog post that may explain it better. Look for the Composition section:
http://aviadezra.blogspot.com/2009/05/uml-association-aggregation-composition.html
I think this representation makes sense for all the objects pictured except maybe StopRequest. Personally I would not have pictured that as a Composition to the Elevator object, but remember that UML is not an exact science.
Your assumption is correct - UML relations doesn't specify the implementation details. In case of composition the requirement is that Motor object lifetime is bounded to the containing Elevator object lifetime. This can be achieved in several ways (and dependens on the language you use as well). It can be a property inside the Elevator and in this case it will be automatically destroyed along with the the containing Elevator. On the other hand, it can be an external object which is instantiated and freed manually during the lifetime of the containing Elevator object. The implementation depends on the specific case and additional design considerations, such as simplicity, flexibility, modularity etc.
There are many details that can be added to the diagram. The creator of the diagram needs to consider what to include and what to omit. For example, private properties are usually related to implementation details and aren't interesting for the class diagram thus they won't be mentioned. Properties mentioned explicitly imply a composition relation between the containing object and the property. Such notion is usually used for primitive properties, such as boolean, int etc. For a more complex properties an explicit UML relation is usually used to depict the relation between the objects (like between Elevator and Motor).
Having the SOLID principles and testability in mind, consider the following case:
You have class A and class B which have some overlapping properties. You want a method that copies and/or converts the common properties from class A to class B. Where does that method go?
Class A as a B GetAsB() ?
Class B as a constructor B(A input)?
Class B as a method void FillWithDataFrom(A input)?
Class C as a static method B ConvertAtoB(A source)?
???
It depends, all make sense in different circumstances; some examples from Java:
String java.lang.StringBuilder.toString()
java.lang.StringBuilder(String source)
void java.util.GregorianCalender.setTime(Date time)
ArrayList<T> java.util.Collections.list(Enumeration<T> e)
Some questions to help you decide:
Which dependency makes more sense? A dependent on B, B dependent on A, neither?
Do you always create a new B from an A, or do you need to fill existing Bs using As?
Are there other classes with similar collaborations, either as data providers for Bs or as targets for As data?
I'd rule out 1. because getter methods should be avoided (tell, don't ask principle).
I'd rule out 2. because it looks like a conversion, and this is not a conversion if A and B are different classes which happens to have something in common. At least, this is what it seems from the description. If that's not the case, 2 would be an option too IMHO.
Does 4. implies that C is aware of inner details of B and/or C? If so, I'd rule out this option too.
I'd vote for 3. then.
Whether this is correct OOP theory or not is up for debate, but depending upon the circumstances, I wouldn't rule C out quite so quickly. While ti DOES create a rather large dependency, it can have it's uses if the specific role of C is to manage the interaction (and copying) from A to B. The dependency is created in C specifically to avoid creating such dependency beteween A and B. Further, C exists specifically to manage the dependency, and can be implemented with that in mind.
Ex. (in vb.Net/Pseudocode):
Public Class C
Public Shared Function BClassFactory(ByVal MyA As A) As B
Dim NewB As New B
With B
.CommonProperty1 = A.CommonProperty1
.CommonProperty2 = A.CommonProperty2
End With
Return B
End Function
End Class
If there is a concrete reason to create, say, a AtoBConverterClass, this approach might be valid.
Again, this might be a specialized case. However I have found it useful on occasion. Especially if there are REALLY IMPORTANT reasons to keep A and B ignorant of eachother.