Java does not support multiple inheritance. One of the reasons is that there could be an ambiguity between methods while inheriting. For example, in the below scenario, there will be an ambiguity to which version of "LevelMethod()" should be inherited in Class “Level3”
class Level1{
public void LevelMethod(){
System.out.println("Level1 method");
}
}
class Level2{
public void LevelMethod(){
System.out.println("Level2 method");
}
}
class Level3 extends Level1,Level2{
}
But, same kind of ambiguity might occur in the following scenario through multi-level inheritance to which version of "LevelMethod()" should be inherited in
Class “Level4”.
class Level1{
public void LevelMethod(){
System.out.println("Level1 method");
}
}
class Level2 extends Level1{
public void LevelMethod(){
System.out.println("Level2 method");
}
}
class Level3 extends Level2{
public void LevelMethod(){
System.out.println("Level3 method");
}
}
class Level4 extends Level3{
}
How java is able to resolve ambiguity in multilevel inheritance, but not in multiple inheritance?
The ambiguity exists when there is no mechanism for conflict resolution.
On single inheritance, the children override the methods on their parents, the method lookup has a clear resolution with no conflicts, since there is an order.
Classic multiple inheritance does not specify conflict resolution mechanism and thus the diamond problem appears.
FYI other models like mixins specify a linearization mechanism for implicit conflict resolution, while traits require you to make explicit the algebra for conflict resolution.
The method being invoked in the inheritance hierarchy will depend on the object type. Each subclass is overriding the parent's "levelMethod".
Try with a few examples
Level1 level = new Level1();
level1.levelMethod(); //Prints "Level1 method"
Level1 level = new Level2();
level.levelMethod(); //Prints "Level2 method"
Level1 level = new Level3();
level.levelMethod(); //Prints "Level3 method"
and so on...
Objects in java are nothing but simply references. So, it doesn't matter whether two or more classes having is-a relationship have same method because it'll depend on which object calls the method, because references will be different (identified by their hashCode). in your given code, if object of Level 2 calls the method LevelMethod() then the context of class Level 2 is been referred, so evidently Java will interpret results from LevelMethod() of Level 2.
But as object of super class can refer object of child class, while calling LevelMethod() you'd need to specify of which class.
If you want to prove that references are different then execute this program:
class A{
public void cmethod(){
System.out.println("Class A");
}
}
class B extends A{
public void cmethod(){
System.out.println("Class B");
}
}
class C extends B{
public void cmethod(){
System.out.println("Class C");
}
}
class MainClass{
public static void main(String[] args){
A aObj = new A();
B bObj = new B();
C cObj = new C();
System.out.println(aObj.toString());
System.out.println(bObj.toString());
System.out.println(cObj.toString());
}
}
Explanation: If you create your own class and don't override the method toString(), then Object class will call it's default toString() method which displays Class#refHashCode (All classes are child class of class Object).
Related
I have two child classes B and C which inherit from one parent class A. Is it possible that I can make certain functions of class A accessible in B but not in C in java?
Well i don't know a way to forbid it in the Code. But you could just override and then don'f fill them.
If what you want is to forbid to call destroyEverything() from class C:
public class A {
public void travel() {
System.out.println("Travel from A");
}
public void makePee() {
System.out.println("Call from A");
}
}
public class B extends A {
public void travel() {
super.travel();
System.out.println("Travel from B");
}
public void makePee() {
super.makePee();
System.out.println("Call from B");
}
}
Then, on C:
public class C extends A {
public void travel() {
super.travel();
System.out.println("Travel from C");
}
public void makePee(){
throw new UnsupportedOperationException("Not supported from C");
}
}
BUT, if what you want is to not inherit stuff from A, it is probably a flaw at the design of your class hierarchy and class C should not inherit from A.
Example of design flaw: Class A is Animal, class B is Beaver, and you want your class C Cadillac to inherit stuff from Animal since Animal already has the method travel.
Since maybe you don't want to inherit the method makePee (every animal urinates, but Cadillacs don't), it is better to move Cadillacs (class C) to another class hierarchy or find another class design
As per my thinking it is not possible.
Let's see the one real time example->
A Parent have a two child then both are able to access parent property .it is there no restriction on that you can not use this or you can not use this.
And if you want to do like that then you can implicitly write logic in B class also
abstract class Base{
protected abstract void a();
}
class Child extends Base{
#Override
public void a(){
//why is this valid
}
}
Why is that we can't reduce the visibility but can increase it?
Also I need to implement Template pattern in which the public methods visible can only be of base class.
Example:
abstract class Base{
public void callA(){
//do some important stuff
a();
}
protected abstract void a();
}
class Child extends Base{
#Override
public void a(){
//why is this valid
}
}
Now if java allows to increase visibility then there are two methods visible publicly??
I know interface is one solution but is there some other way out???
Why decreasing visibility is not allowed is already explained in other responses (it would break the contract of the parent class).
But why it is allowed to increase the visibility of a method? First, it would not break any contract, so there is no reason to not allow it. It can be handy sometimes, when it makes sense in the child class for a method to not be protected.
Second, not allowing it could have the side effect of making impossible sometimes to extend a class and implement an interface at the same time:
interface Interface1 {
public void method();
}
public class Parent {
protected abstract void method();
}
public class Child extends Parent implements Interface1 {
#Override
public void method() {
}
//This would be impossible if the visibility of method() in class Parent could not be increased.
}
About your second question, you can do nothing about it. You have to trust that the person who implements the child class doesn't do anything that breaks your implementation. Even if java wouldn't allow to increase visibility, that would still not fix your problem, because a public method with a different name could be created that calls the abstract method:
class Child extends Base{
#Override
protected void a(){
}
public void a2() {
a(); //This would have the same problems that allowing to increase the visibility.
}
}
If the base class makes a promise regarding visibility, then the subclass cannot break that promise and still satisfy the Liskov substitution principle. You can't use a subclass in any situation where the promised method is exposed if that promise is broken.
The subclass IS-A base class. If the base class exposes a method, so must the subclass.
There's no way out in Java or C++. I'd guess the same is true in C#.
Why is that we can't reduce the visibility but can increase it?
Suppose that it would be possible to reduce the visibility. Then look at the following code:
class Super {
public void method() {
// ...
}
}
class Sub extends Super {
#Override
protected void method() {
// ...
}
}
Suppose that you would have another class, in another package, where you use these classes:
Super a = new Sub();
// Should this be allowed or not?
a.method();
To check whether a method call is allowed or not, the compiler looks at the type of the variable you call it on. The type of the variable a is Super. But the actual object that a refers to is a Sub, and there the method is protected, so you would say it should not be allowed to call the method from an unrelated class outside the package. To solve this strange situation, it's made forbidden to make overridden methods less visible.
Note that the other way around (making a method more visible) doesn't lead to the same problem.
Since Java allows Super class reference to point to sub class object.. So, restriction should not be increased from compile-time to runtime..
Lets see this through an example: -
public class B {
public void meth() {
}
}
class A extends B {
private void meth() { // Decrease visibility.
}
}
Now, you create an object of class A and assign it the reference of class B..
Lets see how: -
B obj = new A(); // Perfectly valid.
obj.meth(); // Compiler only checks the reference class..
// Since meth() method is public in class B, Compiler allows this..
// But at runtime JVM - Crashes..
Now, since compiler only checks the type of the reference variable, and check the visibility of methods in that class (class B), and it doesn't check what kind of object does the reference obj refers to.. So, it is not worried about that.. It is left to JVM at runtime to resolve the appropriate method..
But at runtime, JVM will actually try to invoke the meth method of class A as object is of class A.. But, now what happens... BooooOOMM ---> JVM Crashes.. because meth method is private in class A...
That's why visibility is not allowed to be decreased..
I have a requirement to invoke two different methods from two different classes to my own class and those two classes are in two different .jar files provided by the vendors.
The scenario is something like below:
abc.jar: public class A{ public void m1(){} }
xyz.jar: public class B{ public void m2(){} }
My own class is MyClass{}. If I have to use those two methods in my class I need to extend both the classes, but since java does't support multiple Inheritance, I am not able to achieve it.
Please share if there is any other way to access both m1() & m2() methods in my class.
Note: I have to extend the available functionalities and should customize the methods according to my requirement.
Edit: The question was clarified later, the OP wants to extend the functionalities of the classes.
One idea would be to create two separate sub-classes for the two different base classes. Extend the functionalities in these sub-classes and then use composition in your MyClass to use the functionalities of these sub-classes and their super-classes.
public class SubA extends A {
#Override
public void m1() {
// add extra functionalities
super.m1(); // invoke existing functionalities
}
}
public class SubB extends B {
#Override
public void m2() {
// add extra functionalities
super.m2(); // invoke existing functionalities
}
}
public class MyClass {
SubA a = new SubA();
SubB b = new SubB();
a.m1();
b.m2();
}
You can also refer to this question How do Java Interfaces simulate multiple inheritance? for detailed explanation of how to implement multiple-inheritance in Java.
Earlier answer:
Both the methods are public, so you don't need to extend the classes to use those methods. Just create an object of those two classes and call their respective methods.
A a = new A();
a.m1();
B b = new B();
b.m2();
Maybe I will do this,
class A{
public void m1{};
}
class B{
public void m2{};
}
class OneOverrideA extends A{
#Override
public void m1{};
}
class OneOverrideB extends B{
#Override
public void m2{};
}
class FatherClass extends OneOverrideA{
//well you have your class method m1 here but we cannot extend more than two class
public void m2{new OneOverrideB().m2()};
}
Although it is not awesome in my point of view, anyway why would you want to override both methods? if you're going to do that why not create them from zero? or are you going to use other methods from those class? nvm I would use composition anyway.
Hope it can re fresh your mind and get something from here :) GL
For a project, I have following classes:
SuperClass
Subclass 1
Subclass 2
The two subclasses extend the superclass.
Now, I need a third class with the EXACT behaviour (read, same overriden method implementations) of both SubClass 1 and Subclass 2.
Because Subclass 1 overrides only 1 method in SuperClass, and Subclass 2 doesn't override that method, I want to make the third class inherit Superclass and just implement it with the methods of Subclass 1 and Subclass 2. Now, is this good OO-design? I see no other solution because multiple inheritance in Java just isn't possible. Are there any alternatives?
Java8 introduced default and static methods for interfaces. To a certain degree, that allows for multiple inheritance. But most likely, the correct solution would be to rework your design.
You see, inheritance is not about code re-use. It is about creating useful abstractions; and make good use of polymorphism for example.
In your case: maybe those functionalities could/should be put into smaller interfaces; and then segregated into their own, independent classes. And then you use composition of objects instead of inheritance to build the thing you need.
Here is an example using Java 8's default methods as #GhostCat mentioned. I don't see anything wrong with this OO design per se. Whether or not it's appropriate to your use case depends on the details of the problem you're solving.
public class Main {
public static void main(String... args) {
SuperClass sc = new SubClass3();
sc.foo(); // overridden foo
sc.bar(); // overridden bar
}
interface SuperClass {
default void foo() {
System.out.println("default foo");
}
default void bar() {
System.out.println("default bar");
}
}
interface SubClass1 extends SuperClass {
#Override
default void foo() {
System.out.println("overridden foo");
}
}
interface SubClass2 extends SuperClass {
#Override
default void bar() {
System.out.println("overridden bar");
}
}
static class SubClass3 implements SubClass1, SubClass2 {}
}
If a class is implementing two interfaces, which inteface is actual the parent interface for that class in Java
interface A {
void m1();
}
interface B {
void m1();
}
public class C implements A,B {
public void m1() {
System.out.println("m1 method !!!");
}
public static void main(String[] args) {
C obj = new C();
obj.m1();
((A)obj).m1();
((B)obj).m1();
A objAsA = (A)obj;
objAsA.m1();
B objAsB = (B) obj ;
objAsB.m1();
}
}
There is no such concept as "the actual parent interface" in Java. All interfaces are on equal footing as the supertypes of the class. That doesn't change even in your case where both interfaces declare the same method signature: the same method in C implements both A and B.
BTW you don't need a cast operator to accomplish an upcast:
A objAsA = obj;
objAsA.m1();
B objAsB = obj;
objAsB.m1();
parent is a concept related for extension not implementation.
From Java Java Specification
interface Fish { int getNumberOfScales(); }
interface Piano { int getNumberOfScales(); }
class Tuna implements Fish, Piano {
// You can tune a piano, but can you tuna fish?
public int getNumberOfScales() { return 91; }
}
the method getNumberOfScales in class Tuna has a name, signature, and return type that matches the method declared in interface Fish and also matches the method declared in interface Piano; it is considered to implement both.
So its considered you implement BOTH
Your question doesn't make sense. You do not have 'parent' interfaces in java.
An interface is like a contract, you 'promise' to provide the methods listed in the interface. You are getting inheritance mixed up with interfaces.
Inheritance is where one class inherits parts of another class.
Like Dog -> Husky, Dog -> Poodle
An interface is where every Animal promises to have a method called public String getSpecies() for example.
In case you want to find all the interfaces a class has look at this question.
Determining the extended interfaces of a Class
While an interface can extend other interfaces, a 'normal' class doesn't have the concept of parent interfaces.
Thank you to akhil for spotting this.
You can think of child classes as specialisations of their parents, each level being more specific.
Animal -> Dog -> Husky. However every lower level has some common functionality with its siblings. All Dogs can bark(), all Animals can move().
Now try applying this logic to interfaces and you will see that it doesn't really make sense. An interface exists only to ensure that every class has a specific ability. All animals need to breathe, regardless of what species so you can make Animals implement Breathable. Which ensures that every animal has a method breathe().
Here class C implements both the interfaces and C is A and C is B as well.
An implemenation means you need to use that method in your class. So there is no parent of it. With extendions this can be, but then there can't be 2 parents to 1 class. For example:
public static void main(String[] args){
C c = new C();
c.m1();
}
class A {
public void m1() {
System.out.println("A printing");
}
}
class B {
public void m1() {
System.out.println("B printing");
}
}
class C extends A {
public void m1() {
System.out.println("C print");
}
}
printing: "C print"
C can't extend B at the same time. But it does override the method of class A. If C did not contain the method "m1()" then the method from class A was used and the console would print: "A printing"