I have to design a datastructure that'll get implemented multiple times, and I've struck upon a problem.
Since my datastructure needs to have multiple versions of it, I've created an abstract class that lays the groundwork for all implementations. However, the datastructure requires a set-view of certain parts too.
The problem becomes as follows: The set needs to have different implementations depending on the implementation of my datastructure: Either the HashSet or the Collections.SingletonSet. The two implementing datastructures will then extend bits of these to do additional tasks when items are added or removed from the set. However, the abstract datastructure also requires a way to internally remove elements from this set such that this extra work isn't done. For this I'd like to add a protected method to the set, but I can't!
To illustrate, here's some sample code relating to the type of datastructure I'm creating:
public abstract class AbstractEdge {
public abstract AbstractSetView destination(); //Gives a subclass of AbstractSetView in implementations.
public void doStuff() {
destination().removeInternal(foo);
}
public abstract class AbstractSetView implements Set<Vertex> {
protected abstract void removeInternal(Vertex vert);
}
}
public class Edge extends AbstractEdge {
public SetView destination() {
return new SetView();
}
public class SetView extends AbstractSetView,Collections.SingletonSet<Vertex> { //Doesn't work this way.
protected void removeInternal(Vertex vert) {
//Do stuff.
}
}
}
public class HyperEdge extends AbstractEdge {
public SetView destination() {
return new SetView();
}
public class SetView extends AbstractSetView,HashSet<Vertex> { //Doesn't work this way.
protected void removeInternal(Vertex vert) {
//Do stuff.
}
}
}
These are the options I've considered:
As above, extending from multiple classes isn't allowed.
Making the AbstractSetView an interface causes the removeInternal() method to become public, which is undesirable.
Making SetView extend only AbstractSetView and implement everything myself... twice. But this requires me to basically include HashSet and SingletonSet implementations, as an inner class, which is extremely ugly.
Surely the designers of Java made some way around this, to enable me to use their built-in Set implementations? What am I overlooking?
No, they did not "make some way around this" because they didn't see any obstacle, problem, or limitation. According to them, multiple inheritance was not really needed in the language because at least 85% of the time it is used when what really corresponds is composition. 14% of the remaining cases can be solved through interfaces and non-natural use of composition, and 1% with code replication. True: the later is U.G.L.Y. and R.E.D.U.N.D.A.N.T. and U.N.S.A.F.E., etc, but the main objective was to create a small language that could be implemented even in embedded devices. They were not going to give this up for just 1% of the cases. IMHO, they were about right in the percentages.
To answer your second question: don't inherit, especially from library classes, when what you really need is composition. Make AbstractEdge have a member protected Set backingSet; which is initialized with different Set implementations by the subclasses. This is implies that you don't need AbstractSetView and its subclasses.
Otherwise, member protected Set backingSet; can be located in AbstractSetView.
The two answers given so far both offer a solution and advice for the Set case. However, a pattern you can use in this and other similar situations (for example, you are not extending a JRE class, but your own stuff) is to split the interface in a public and an inner protected one.
Your public interface, in this case, will be Set.
Your protected inner interface will be InternalSet, declared inside AbstractEdge, defining the removeInternal method. The method will be "public", but the interface does not need to be.
Then, the abstract super class should define a public method returning the public interface for use outside your subclasses, and a protected one returning the protected interface for internal use only.
Implementing subclasses can then implement a class, extending whatever Set you need, and also implementing the protected class, and return an instance of it from both methods.
The choice between composition or inheriting from JRE classes is all yours.
Related
I have an abstract class (showing only the relevant parts) with two overloaded methods.
abstract public class Component {
...
abstract protected void createPhysics();
abstract protected void createPhysics(Comp1D[] comp1DS);
...
}
In the subclasses which extend this abstract class I only want to use either the one with arguments or the one without, but never both of them. For example
public class Comp1D extends Component{
...
protected void createPhysics(Comp1D[] comp1Ds){
...
}
}
and
public class Comp3D extends Component{
...
protected void createPhysics(){
...
}
}
Of course this won't compile this way since the other createPhysics method is not implemented in the subclass. My quick and dirty solution would be to implement both methods in subclasses, but the unused method would have empty body.
Is there a more elegant way to solve it in Java 8?
With abstract methods, there is not. And on a syntactical level, it would not be sound either. If one has a Component, one can call both methods. How should one know which one is implemented and which one is not?
One could define both method in the abstract class and let them throw, for example, an UnsupportedOperationException, thus forcing sublcasses to override (at least one of) those methods if they wish to not throw such an exception. This, however, seems like a workaround for another problem.
I would suggest re-evaluating the overall architecture of that section and find another solution to the problem. For example, maybe two separated classes and handler for those classes would yield a cleaner architecture.
The question is, why do you want to use an Abstract class here. What if you plan to use an interface, with default implementations. You can implement the interface and override only the required method
The idea of using abstract class is when you want to define common method signatures in the class and force sub-classes to provide implementation for such methods. From this point of view the way you are trying to implement abstract class doesn't make much sense.
You can also use abstract class to define a base type to support O-O features like polymorphism and inheritance and i think this is what are you trying to do .
If this is the case i suggest to declare an abstract class without abstract methods or declare an interface with default implementation for both methods and then you can override in implementation classes.
As #Turning85 pointed out, such an implementation would not make much sense.
Either you want to give your successor classes the flexibility to implement both of the methods according to their own specific needs or you want to take this complexity away from them and implement the whole logic in the abstract class, where you could have something like this:
abstract class Component() {
protected void createDefaultPhysics() {
//implement
}
abstract protected void createPhysics(Comp1D[] comp1DS);
}
and your concrete classes:
public class Comp1D extends Component{
protected void createPhysics(Comp1D[] comp1Ds){
if(comp1Ds == null) {
createDefaultPhysics();
}
}
}
I am not asking this -> Why is there no multiple inheritance in Java, but implementing multiple interfaces is allowed?
In Java, multiple inheritance isn't allowed, but, after Java 8, Interfaces can have default methods (can implement methods itself), just like abstract classes. Within this context, it multiple inheritance should also be allowed.
interface TestInterface
{
// abstract method
public void square(int a);
// default method
default void show()
{
System.out.println("Default Method Executed");
}
}
Things are not so simple.
If a class implements multiple interfaces that defines default methods with the same signature the compiler will force you to override this method for the class.
For example with these two interfaces :
public interface Foo {
default void doThat() {
// ...
}
}
public interface Bar {
default void doThat() {
// ...
}
}
It will not compile :
public class FooBar implements Foo, Bar{
}
You should define/override the method to remove the ambiguity.
You could for example delegate to the Bar implementation such as :
public class FooBar implements Foo, Bar{
#Override
public void doThat() {
Bar.super.doThat();
}
}
or delegate to the Foo implementation such as : :
public class FooBar implements Foo, Bar {
#Override
public void doThat() {
Foo.super.doThat();
}
}
or still define another behavior :
public class FooBar implements Foo, Bar {
#Override
public void doThat() {
// ...
}
}
That constraint shows that Java doesn't allow multiple inheritancy even for interface default methods.
I think that we cannot apply the same logic for multiple inheritances because multiples issues could occur which the main are :
overriding/removing the ambiguity for a method in both inherited classes could introduce side effects and change the overall behavior of the inherited classes if they rely on this method internally. With default interfaces this risk is also around but it should be much less rare since default methods are not designed to introduce complex processings such as multiple internal invocations inside the class or to be stateful (indeed interfaces cannot host instance field).
how to inherit multiple fields ? And even if the language allowed it you would have exactly the same issue as this previously quoted : side effect in the behavior of the inherited class : a int foo field defined in a A and B class that you want to subclass doesn't have the same meaning and intention.
The language designers already thought about that, so these things are enforced by the compiler. So if you define:
interface First {
default void go() {
}
}
interface Second {
default void go() {
}
}
And you implement a class for both interfaces:
static class Impl implements First, Second {
}
you will get a compilation error; and you would need to override go to not create the ambiguity around it.
But you could be thinking that you can trick the compiler here, by doing:
interface First {
public default void go() {
}
}
static abstract class Second {
abstract void go();
}
static class Impl extends Second implements First {
}
You could think that First::go already provides an implementation for Second::go and it should be fine. This is too taken care of, thus this does not compile either.
JLS 9.4.1.3 : Similarly, when an abstract and a default method with matching signatures are inherited, we produce an error. In this case, it would be possible to give priority to one or the other - perhaps we would assume that the default method provides a reasonable implementation for the abstract method, too. But this is risky, since other than the coincidental name and signature, we have no reason to believe that the default method behaves consistently with the abstract method's contract - the default method may not have even existed when the subinterface was originally developed. It is safer in this situation to ask the user to actively assert that the default implementation is appropriate (via an overriding declaration).
The last point I would bring in, to solidify that multiple inheritance is not allowed even with new additions in java, is that static methods from interfaces are not inherited. static methods are inherited by default:
static class Bug {
static void printIt() {
System.out.println("Bug...");
}
}
static class Spectre extends Bug {
static void test() {
printIt(); // this will work just fine
}
}
But if we change that for an interface (and you can implement multiple interfaces, unlike classes):
interface Bug {
static void printIt() {
System.out.println("Bug...");
}
}
static class Spectre implements Bug {
static void test() {
printIt(); // this will not compile
}
}
Now, this is prohibited by the compiler and JLS too:
JLS 8.4.8 : A class does not inherit static methods from its superinterfaces.
Java doesn't allow multiple inheritance for fields. This would be difficult to support in the JVM as you can only have references to the start of an object where the header is, not arbitrary memory locations.
In Oracle/Openjdk, objects have a header followed by the fields of the most super class, then the next most super class, etc. It would be a significant change to allow the fields of a class to appear at different offsets relative to the header of an object for different subclasses. Most likely object references would have to become a reference to the object header and a reference to the fields to support this.
default methods in interfaces pose a problem that :
If both of the implemented interfaces define a default method with
same method signature, then the implementation class does not know
which default method to use.
The implementation class should define explicitly specify which default method to use or define it's own one.
Thus default methods in Java-8 do not facilitate multiple inheritance. The main motivation behind default methods is that if at some point we need to add a method to an existing interface, we can add a method without changing the existing implementation classes. In this way, the interface is still compatible with older versions. However, we should remember the motivation of using Default Methods and should keep the separation of interface and implementation.
The main issues with multiple inheritance are ordering (for overriding and calls to super), fields and constructors; interfaces don't have fields or constructors, so they don't cause problems.
If you look at other languages they usually fall in two broad categories:
Languages with multiple inheritance plus a few features to disambiguate special cases: virtual inheritance [C++], direct calls to all superconstructors in the most-derived class [C++], linearization of superclasses [Python], complex rules for super [Python], etc.
Languages with a differente concept, usually called interfaces, traits, mixins, modules, etc. that impose some limitations such as: no constructors [Java] or no constructors with parameters [Scala until very recently], no mutable fields [Java], specific rules for overriding (e.g. mixins take precedence over base classes [Ruby] so you can include them when you need a bunch of utility methods), etc. Java has become a language like these.
Why just by disallowing fields and constructors you solve many issues related to multiple inheritance?
You can't have duplicated fields in duplicated base classes.
The main class hierarchy is still linear.
You can't construct your base objects the wrong way.
Imagine if Object had public/protected fields and all subclasses had constructors setting those fields. When you inherit from more than one class (all of them derived from Object), which one gets to set the fields? The last class? They become siblings in the hierarchy, so they know nothing about each other. Should you have multiple copies of Object to avoid this? Would all classes interoperate correctly?
Remember that fields in Java are not virtual (overridable), they are simply data storage.
You could make a language where fields behave like methods and could be overridden (the actual storage would be always private), but that would be a much bigger change and problably wouldn't be called Java anymore.
Interfaces can't be instantiated by themselves.
You should always combine them with a concrete class. That eliminates the need for constructors and makes the programmer's intent clearer too (that is, what is meant to be a concrete class and what's an accessory interface/mixin). This also provides a well-defined place to solve all ambiguities: the concrete class.
That is mostly related to "diamonds problem" i think. Right now if you implement multiple interfaces with the same method, compiler forces you to override method the one you want to implement, because it don't know which on to use. I guess Java creators wanted to remove this problem back when interfaces couldn't use default methods. Now they came up with idea, that is good to be able to have methods with implementation in interfaces, as you can still use those as functional interfaces in streams / lambda expressions and utilize their default methods in processing. You cannot do that with classes but diamond problem still exist there. That is my guess :)
class A{
void m1(){
System.out.println("m1-A");
}
}
class B{
void m1(){
System.out.println("m1-B");
}
}
class C extends A, B{ // this will give an error
// inheritance means making all variables and/or methods available to the child class, here child class will get confused as which m1() method to inherit, hence an error
}
JAVA DOES SUPPORT MULTIPLE INHERITANCE.
If you make a OVERALL COMPARISON OF THE PROGRAMMING LANGUAGE,JAVA,THEN YOU COME TO KNOW THAT I AM TRUE.
Java's topclass or the root class in the Ancestor Hierarchy is the Object class.
This class is a Superclass of all other classes. Hence, each class in Java that we declare or is predefined in the API itself inherits this Object class.
Moreover, Java provides us to inherit one more class of our choice.
Hence, we can say that we are performing INTERLOCKED BUT MULTIPLE INHERITANCE.
2ND Way
Java supports Multiple Inheritance of Interfaces. So you can use as many interface implementations you want. But note, implementing an interface does not define IS A relationship as in case of Inheritance of Classes is possible.
I have two classes. Let's call them PostClass and CommentClass. Both classes implement the Reportable interface:
public interface Reportable {
void report();
boolean isReported();
. . .
Now I need to add two additional methods to each one of the classes. These methods logically fit into the same interface but needs to have different names. For example:
PostClass will have methods -> remove(), restore()
CommentClass will have methods -> hide(), show()
Question: What would be the preferred way to design this change? The options are as I see it:
Create an additional interface which will extend the Reportable interface. Problem: Too many interfaces
Add all four new methods into the Reportable interface and then just leave the irrelevant two methods unimplemented in each class. Problem: Untidy/ugly
Don't worry about having a few more interfaces, as long as their use and purpose is clear. These 2 options are valid:
PostClass implements RemovableReportable, which extends Reportable; And
CommentClass implements HideableReportable, which extends Reportable.
PostClass implements both Reportable and Removable; And
CommentClass implements both Reportable and Hideable.
But adding all four new methods into the Reportable interface and leaving two methods unimplemented in each class is very wrong, since it does not lead to code which is clean and easy to understand and use. The developer would have to learn which method to use in each case, thus making your code more difficult to use and modify. And what happens if some developer calls the wrong method? If the wrong method does nothing, bugs may go unnoticed. If it throws an exception, this will only catch bugs at runtime. And if it calls the other method then you have two ways of doing the same thing, which is also bad and confusing.
Unused methods in an interface are a code smell, and may indicate a design flaw.
If they do the same thing, then make up names that encompass the function; although that doesn't sound like what you want given the existing names.
Option 3: Create two new interfaces, Removable and Hideable and have each class implement the appropriate interface(s).
On second thought, I would probably recommend using hide() and show() since that seems to capture what's happening best.
While the question would likely be classified as opinion based, my approach would be to still add two methods (show(),hide()) to the interface and have the classes implement it.
Below are few other options :
If you are using JDK8 you can try adding the above two methods as default-methods in the interface so that it does not immediately break the existing implementation.
Also, apparently its possible to invoke the abstract method from a default method in the interface so it would technically be possible to have two generically named abstract methods and two (or four more) that are specifically named default methods but that would be overkill and would only add to the confusion.
You could consider having a total of six new methods. show and hide being abstract and also showPost/hidePost and showComment and hideComment being default classes which in turn invoke the abstract show and hide respectively. That way even if some implementation class calls the wrong alias by mistake it would still invoke the correct implementation (in theory).
Whatever I am going to describe in this answer is purely my opinion and subjective.
The following points must be kept in mind when designing this:
Any method added to Reportable (or in general any supertype) should be applicable to all subtypes regardless.
A method should describe a behaviour of the class, something that the class is capable of 'doing'.
Point 2 explanation
Think of the method postClass.remove(), which can be read as 'A PostClass knows how to remove...'. But remove what? Itself? From where?
For me, 'removing' and 'restoring/adding' seems like something that can be done on a Collection of PostClass or CommentClass by and not something that these classes do themselves. If I guess correctly, this is indeed how you must be using PostClass and CommentClass in your application (i.e. as a Collection of some sort). Now, a PostClass or CommentClass can get a callback onRemove(), onRestore(), onHide() or onShow() to do what's necessary for each of this actions when being removed/restored/hidden/shown.
The advantage of callbacks is that a class can choose to call super if they don't intend to do something special during the action.
Design 1 - Reportable has the behaviour of being hidden,shown,restored and removed
So, for all 'reports' of your application, you can add these callbacks to the Reportable interface itself.
public interface Reportable {
void report();
boolean isReported();
void onRestore();
void onRemove();
void onHide();
void onShow();
}
Usage could be something like this
public class User {
private List<Reportable> reports;
//... more User related code
public void deleteReport(Reportable report) {
//give report a chance to cleanup
report.onDelete();
//delete from user's list of reports
this.reports.remove(report);
//more code
}
Design 2 - Having separate interfaces
public interface Viewable {
void onHide();
void onShow();
}
public interface Disposable {
void onRemove();
void onRestore();
}
public class PostClass implements Reportable, Disposable {
}
public class CommentClass implements Reportable, Viewable {
}
Usage for this is pretty self explanatory I guess.
I prefer Design 2 as it seems more clean and adheres to 'SOLID' design principles.
Hope this helps.
I have an interface with a lot of methods. (which i cannot split into different interfaces)
When i create a class that implements the interface i get a lot of methods in 1 class file.
Things get worst when the body of all these methods get larger -> the class file becomes huge and quite difficult to navigate.
Even with ide's like eclipse because the Outline window containing all classes get a vertical scrollbar because not all methods can fit in the outline.
Is there a pattern that prevents this from happening?
No there is no way to split the implementation in many classes.
But you can delegate from the implementing class to any other classes.
This will reduce the code in the implementation but the number of methods stay the same.
I am posting this reply after an answer is accepted, hoping that future comers might find it useful.
As simas_ch said:
No there is no way to split the implementation in many classes. But
you can delegate from the implementing class to any other classes.
This will reduce the code in the implementation but the number of
methods stay the same.
Once I worked on a rather huge application in which I had to define a Lifecycle interface, which contained many states and many functions that could create a hassle, so I came around with something like this:
You can create a class and make it abstract and implement most of the common functions.
public interface TheBigFunctional {
public void functionalA();
public void functionalB();
public void functionalC();
//....
public void functionalZ();
}
public abstract class FunctionalBase implements TheBigFunctional {
public void functionalA() {
aInternal();
}
protected abstract void aInternal();
// Rest of methods implementations.
// You may choose to skip those if you want child classes to implement them.
}
public class FunctionalTypeFoo extends FunctionalBase {
// Implementations.
}
public class FunctionalTypeBar extends FunctionalBase {
// Implementations.
}
There are many (good) ways to come around the sitation, but I am sharing what I did.
I do not quite understand why you cannot split the interface into multiple ones...
I surely would try to use inheritance, like:
First interface:
public interface FatherInterface {
String methodOne(String var);
String methodTwo(String var);
String methodThree(String var);
}
Second interface:
public interface SonInterface extends FatherInterface {
String methodFour(String var);
String methodFive(String var);
}
Third interface:
public interface SecondSonInterface extends SonInterface {
String methodSix(String var);
String methodSeven(String var);
}
And so on... Each interface inheriting from the preceding one.
As for class files becoming large, go with inheritance too.
Father class:
public class Father implements FatherInterface
Son class:
public class Son extends Father implements SonInterface
And so on...
Edit
If you cannot split the interface (as when given by third party), I would do the implementations of the methods by parts. That is, only some of them implemented in each class. Using abstract classes if needed (or leaving blank methods). Each class inheriting from the above and implementing some of the remaining methods.
Perhaps you could employ the strategy pattern on the big interface by implementing some of those methods from different classes. Then, when you wish to use any of those methods, simply call it from the class that implements your 'large' interface.
More on strategy pattern here: https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm
In this case i would consider whether all methods in your class are well designed. Probably they do not have clear purpose and should be splitted per few.
You have to define clear purpose of some particular interface.
Besides, if you are using Java 8, consider ability to provide some default implementation for some methods.
Is there a pattern that prevents this from happening?
In Java:
Subtyping: If you can group sets of methods into different interfaces such that a clear hierarchical relation makes sense. This is what the accepted answer is assuming.
Interface Segregation: If you can group sets of methods into different sibling "domains" or "categories". Take a look at this example from jcabi-github. See how Github is this API's entrypoint, while exposing different sets of functionalities via successive "grouping" interfaces.
First of all... Sorry for this post. I know that there are many many posts on stackoverflow which are discussing multiple inheritance. But I already know that Java does not support multiple inheritance and I know that using interfaces should be an alternative. But I don't get it and see my dilemma:
I have to make changes on a very very large and complex tool written in Java. In this tool there is a data structure built with many different class objects with a linked member hierarchy. Anyway...
I have one class Tagged which has multiple methods and returns an object tag depending on the object's class. It needs members and static variables.
And a second class called XMLElement allows to link objects and in the end generate a XML file. I also need member and static variables here.
Finally, I have these many many data classes which nearly all should extend XMLElement and some of them Tagged.
Ok ok, this won't work since it's only possible to extend just one class. I read very often that everything with Java is ok and there is no need for having multiple inheritance. I believe, but I don't see how an interface should replace inheritance.
It makes no sense to put the real implementation in all data classes since it is the same every time but this would be necessary with interfaces (I think).
I don't see how I could change one of my inheritance classes to an interface. I have variables in here and they have to be exactly there.
I really don't get it so please can somebody explain me how to handle this?
Actually, I have no good answer other than Java SHOULD have Multiple Inheritance. The whole point that interfaces should be able to replace the need for Multiple Inheritance is like the big lie that when repeated enough times becomes true.
The argument is that Multiple Inheritance causes all these problems (la-di-dah), yet I keep hearing those arguments from Java developers who have never used C++. I also don't EVER remember C++ programmers saying "Gee, I love C++, but if they would only get rid of Multiple Inheritance, it would become a great language". People used it when it was practical and didn't when it wasn't.
Your problem is a classic case of where Multiple Inheritance would be appropriate. Any suggestion to refactor the code is really telling you how to work around the PROBLEM that Java has no Multiple Inheritance.
Also all the discussion that "oh, delegation is better, la-di-dah" is confusing religion with design. There is no right way. Things are either more useful or less useful and that is all.
In your case Multiple Inheritance would be more useful and a more elegant solution.
As far as refactoring your code into a less useful form to satisfy all the religious people who have never used Multiple Inheritance and believe "Multiple Inheritance is bad", I guess you will have to downgrade your code because I don't see Java "improving" in that way any time soon. There are too many people repeating the religious mantra to the point of stupidity that I can't see it ever being added to the language.
Actually, my solution for you would be "x extends Tagged, XMLElement" and that would be all.
...but as you can see from the solutions provided above, most people think that such a solution would be WAY TOO COMPLEX AND CONFUSING!
I would prefer to venture into the "x extends a,b" territory myself, even if it is a very frightening solution that might overwhelm the abilities of most Java programmers.
What is even more amazing about the solutions suggested above is that everyone here who suggested that you refactor your code into "delegation" because Multiple Inheritance is bad, would, if they were confronted with the very same problem, would solve the problem by simply doing: "x extends a,b" and be done with it, and all their religious arguments about "delegation vs inheritance" would disappear. The whole debate is stupid, and it only being advanced by clueless programmers who only demonstrate how well they can recite out of a book and how little they can think for themselves.
You are 100% correct that Multiple Inheritance would help, and no, you are doing anything wrong in your code if you think Java should have it.
You should probably favor composition (and delegation) over inheritance :
public interface TaggedInterface {
void foo();
}
public interface XMLElementInterface {
void bar();
}
public class Tagged implements TaggedInterface {
// ...
}
public class XMLElement implements XMLElementInterface {
// ...
}
public class TaggedXmlElement implements TaggedInterface, XMLElementInterface {
private TaggedInterface tagged;
private XMLElementInterface xmlElement;
public TaggedXmlElement(TaggedInterface tagged, XMLElementInterface xmlElement) {
this.tagged = tagged;
this.xmlElement = xmlElement;
}
public void foo() {
this.tagged.foo();
}
public void bar() {
this.xmlElement.bar();
}
public static void main(String[] args) {
TaggedXmlElement t = new TaggedXmlElement(new Tagged(), new XMLElement());
t.foo();
t.bar();
}
}
Similar to what Andreas_D suggested but with the use of inner classes. This way you indeed extend each class and can override it in your own code if desired.
interface IBird {
public void layEgg();
}
interface IMammal {
public void giveMilk();
}
class Bird implements IBird {
public void layEgg() {
System.out.println("Laying eggs...");
}
}
class Mammal implements IMammal {
public void giveMilk() {
System.out.println("Giving milk...");
}
}
class Platypus implements IMammal, IBird {
private class LayingEggAnimal extends Bird {}
private class GivingMilkAnimal extends Mammal {}
private LayingEggAnimal layingEggAnimal = new LayingEggAnimal();
private GivingMilkAnimal givingMilkAnimal = new GivingMilkAnimal();
#Override
public void layEgg() {
layingEggAnimal.layEgg();
}
#Override
public void giveMilk() {
givingMilkAnimal.giveMilk();
}
}
First it makes no sense to put the real implementation in all data classes since it is the same every time but this would be necessary with interfaces (I think).
How about using aggregation for the tags?
Rename your Tagged class to Tags.
Create a Tagged interface:
interface Tagged {
Tags getTags();
}
Let each class that needs to be "tagged", implement Tagged and let it have a tags field, which is returned from getTags.
Second I don't see how I could change one of my inheritance classes to an interface. I have variables in here and they have to be exactly there.
That's right, interfaces can't have instance variables. The data structures storing the tags however, shouldn't necessarily IMO be part of the classes that are tagged. Factor out the tags in a separate data structure.
I'd solve it that way: extract interfaces for the Tagged and XMLElement class (maybe you don't need all methods in the public interface). Then, implement both interfaces and the implementing class has a Tagged (your actual concrete Tagged class) and an XMLElement (your actual concrete XMLElement class):
public class MyClass implements Tagged, XMLElement {
private Tagged tagged;
private XMLElement xmlElement;
public MyClass(/*...*/) {
tagged = new TaggedImpl();
xmlElement = new XMLElementImpl();
}
#Override
public void someTaggedMethod() {
tagged.someTaggedMethod();
}
}
public class TaggedImpl implements Tagged {
#Override
public void someTaggedMethod() {
// so what has to be done
}
}
public interface Tagged {
public void someTaggedMethod();
}
(and the same for XMLElement)
one possible way;
1- You can create base class(es) for common functionality, make it abstract if you dont need to instantiate it.
2- Create interfaces and implement those interfaces in those base class(es). If specific implementation is needed, make the method abstract. each concrete class can have its own impl.
3- extend the abstract base class for in concrete class(es) and implement specific interfaces at this level as well
Just wondering if one could not simply use inner (member) classes (LRM 5.3.7)?
E.g. like this (based on the first answer above):
// original classes:
public class Tagged {
// ...
}
public class XMLElement {
// ...
}
public class TaggedXmlElement {
public/protected/private (static?) class InnerTagged extends Tagged {
// ...
}
public/protected/private (static?) class InnerXmlElement extends XMLElement {
// ...
}
}
This way you have a class TaggedXmlElement which actually contains all elements from the two original classes and within TaggedXmlElement you have access to non-private members of the member classes. Of course one would not use "super", but call member class methods.
Alternatively one could extend one of the classes and make the other a member class.
There are some restrictions, but I think they can all be worked around.
Well using Interface and single base class you are simply stating:
A) One object can be of only one type (Which is true in real life if you think ,
A pigeon is a bird, a toyota is a car , etc .. A pigeon is also an animal but every bird is animal anyway, so its hierarchically above the bird type -And in your OOP design Animal class should be base of Bird class in case you need to represent it -)
and
B) can do many different things (A bird can sing, can fly . A car can run , can stop ,etc..) which also fits the real life objects.
In a world where objects can be of multiple types (horizontally)
Let's say a a dolphin is a mammal and also a sea animal, in this case multiple inheritance would make more sense. It would be easier to represent it using multiple inheritance.
Using composition would be the way to go as another developer suggested. The main argument against multiple inheritance is the ambiguity created when you're extending from two classes with the same method declaration (same method name & parameters). Personally, however, I think that's a load of crap. A compilation error could easily be thrown in this situation, which wouldn't be much different from defining multiple methods of the same name in a single class. Something like the following code snippet could easily solve this dilema:
public MyExtendedClass extends ClassA, ClassB {
public duplicateMethodName() {
return ClassA.duplicateMethodName();
}
}
Another argument against multiple inheritance is that Java was trying to keep things simple so that amateur developers don't create a web of interdependent classes that could create a messy, confusing software system. But as you see in your case, it also complicates and confuses things when it's not available. Plus, that argument could be used for a 100 other things in coding, which is why development teams have code reviews, style checking software, and nightly builds.
In your particular situation though, you'll have to settle with composition (see Shojaei Baghini's answer). It adds a bit of boiler plate code, but it emulates the same behavior as multiple inheritance.
I run in a similar problem on Android. I needed to extend a Button and a TextView (both inheriting from View) with additional functions. Due to not having access to their super class, I needed to find another solution. I´ve written a new class which encapsulates all the implementations:
class YourButton extends Button implements YourFunctionSet {
private Modifier modifier;
public YourButton(Context context) {
super(context);
modifier = new Modifier(this);
}
public YourButton(Context context, AttributeSet attrs) {
super(context, attrs);
modifier = new Modifier(this);
}
public YourButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
modifier = new Modifier(this);
}
#Override
public void generateRandomBackgroundColor() {
modifier.generateRandomBackgroundColor();
}
}
class Modifier implements YourFunctionSet {
private View view;
public Modifier(View view) {
this.view = view;
}
#Override
public void generateRandomBackgroundColor() {
/**
* Your shared code
*
* ......
*
* view.setBackgroundColor(randomColor);
*/
}
}
interface YourFunctionSet {
void generateRandomBackgroundColor();
}
The problem here is, your classes need the same super class. You can also try to use different classes, but check which type it is from, for example
public class Modifier{
private View view;
private AnotherClass anotherClass;
public Modifier(Object object) {
if (object instanceof View) {
this.view = (View) object;
} else if (object instanceof AnotherClass) {
this.anotherClass = (AnotherClass) object;
}
}
public void generateRandomBackgroundColor(){
if(view!=null){
//...do
}else if(anotherClass!=null){
//...do
}
}
}
So here is basically my Modifier class the class which encapsulates all implementations.
Hope this helps someone.