overriding, overloading and hiding in OOP - java

I know these 3 concepts.
But I remember there was another definition:
Say a base class has 2 virtual methods: Foo() and Foo(int a).
Is there any rule that when a derived class overrides Foo(int a) has to override all other overloads of Foo ?
Was it in Java? I believe it dosn't exist in C#.
Thanks

No, there is no such rule, at least not in Java. Such a rule would be incredibly limiting as sometimes a subclass only has a new implementation of one of those overloads, etc.

This is not a rule in Java. Were you thinking of an interface? If a class implements an interface it must have an implementation of each method declared on the interface.

C++:
What you are referring to is name hiding in C++. When you have a class with overrided methods, and you extend this class an override one of the overrided methods, you need to override all the overloaded methods. If not, calls to non-overridden overloaded in the extended class won't work.
For example:
class Base {
public:
virtual void A (int);
virtual void A (int, int);
};
void Base::A(int i) {
std::cout << “Hi\n”;
}
void Base::A (int i, int j) {
std::cout << “Bye!!\n”;
}
Suppose you only override one of the methods:
class Sub: public Base {
public:
void A(int);
};
void Sub::A(int i) {
std::cout << “Hey, La!\n”;
}
void main () {
Sub a;
a.A(1);
a.A(1, 1);//won't compile
}
The second call won’t work, as A(int, int) is not visible. This is name hiding.
If you want to circumvent this, you can use the using keyword as follows:
class Sub: public Base {
public:
void A(int);
using Base::A;
};
void Sub::A(int i) {
std::cout << “Hey, La!\n”;
}
void main () {
Sub a;
a.A(1);
a.A(1, 1);//will compile
}
Java:
Java doesn't have such a concept though. You can try this out yourself. Note that all Java methods are virtual by default as per virtual C++ methods.
public class Base {
public void A() {
System.out.println("Hi");
}
public void A(int i, int j) {
System.out.println("Bye");
}
}
public class Sub extends Base {
public void A() {
System.out.println("Hey, La!");
}
}
public class Test {
public static void main(String[] args) {
Sub a = new Sub();
a.A();
a.A(1, 1);//perfectly fine
}
}
Aside:
I hope you're not referring to extending an abstract class- if you extend an abstract class, you need to override all abstract methods else your class has to be declared abstract.
All methods of an implemented interface need to be implemented though.

No Actually that does not apply in Java. However if you implement an interface, then you need to have implementation for all methods in it. But when you are using extends i.e inheritance, then you override the methods you want, and in this case the Foo(int x) is different from the Foo() regardless if their return types are the same or not.

However if you want to create non-abstract class (extending a base class), you have to implement all abstract methods.

just to add to what others have already said, in java each method is identified distinctly using its full signature which includes its return type, name and arguments. so when you define a abstract method(virtual function) you define it as abstract only for that function with its signature.
anyhow you could have tried this in ur IDE for fun and would have got the answer in a minute. :P

Related

static method in class have same signature as default method in interface

I have below scenario :
class C {
static void m1() {}
}
interface I {
default void m1() {}
}
//this will give compilation error : inherited method from C cannot hide public abstract method in I
class Main extends C implements I {
}
Below are my questions:
I am aware that instance method will override the default methods but what if static methods in class have same signature as default method in Interface?
If static method m1() in class C would be public then compilation error will be :
static method m1() conflicts with abstract method in I.
so when the access modifier was default it was trying to hide and when it is public it is conflicting. why is this difference? what is the concept behind it?
Ultimately that boils down to the fact that when you have something like this:
class Me {
public static void go() {
System.out.println("going");
}
}
These both would be allowed:
Me.go();
Me meAgain = new Me();
meAgain.go(); // with a warning here
Intersting is that this would work too for example:
Me meAgain = null;
meAgain.go();
Personally I still see this as design flaw that could not be retracted due to compatibility - but I wish the compiler would not allow me to access the static method from an instance.
Your first question is not related to java-8 per-se, it has been like this before java-8:
interface ITest {
public void go();
}
class Test implements ITest {
public static void go() { // fails to compile
}
}
default methods just follow the same rule here. Why this happens is actually detailed quite a lot on stack overflow - but the underlying idea is that potentially this would cause confusion on which method to call (imagine ITest would be a class that Test would extends and you do ITest test = new Test(); test.go(); -> which method are you calling?)
I think that for the same reasons this is not allowed also (which is basically your second question, otherwise you would have a static and non-static method with the same signatures)
static class Me {
static void go() {
}
void go() {
}
}
It's interesting that this is sort of fixed (I guess that they realized it would be really bad to do the same mistake again) in method references:
static class Mapper {
static int increment(int x) {
return x + 1;
}
int decrement(int x) {
return x - 1;
}
}
Mapper m = new Mapper();
IntStream.of(1, 2, 3).map(m::increment); // will not compile
IntStream.of(1, 2, 3).map(m::decrement); // will compile
Answering your 1st question:
Both the "static method in class" and the "default method in interface" are available to the class Main, and hence if they have the same signature, it will create ambiguity.
For example:
class C{
static void m1(){System.out.println("m1 from C");}
}
public class Main extends C{
public static void main(String[] args) {
Main main=new Main();
main.m1();
}
}
Output: m1 from C
Similarly,
interface I{
default void m1(){System.out.println("m1 from I");}
}
public class Main implements I{
public static void main(String[] args) {
Main main=new Main();
main.m1();
}
}
Output: m1 from I
As you can see, both these can be accessed similarly. So this is also the reason for conflict when you implement I and extend C.
Answering your second question:
If your classed and interfaces are in the same package, the default and public access modifier should work similarly.
Also, m1() in C is static which cannot be overridden, and hence it cannot be considered as implementation of m1() in I and so the compilation issue.
Hope that helps!
I will answer your first question since the second is already answered
I am aware that instance method will override the default methods but
what if static methods in class have same signature as default method
in Interface?
I am assuming you are using JDK 1.8 and hence the confusion. default modifier in an interface method is not talking about its access specifications. Instead it mentions that the interface itself need to implement this method. Access specification for the method is still public. Starting from JDK8 , interfaces allow you specify methods with default modifer to allow to extend interfaces in a backward compatible way.
In your interface you had to give default void m1() {} for the compilation to be successfull. Normally we simply define them in an abstract way like void m1(); in an interface You had to implement the method because you specified the method as default. Hope you understand.
Because class methods in java can also be called using instance variables, this construct will lead to ambiguities:
Main m = new Main();
m.m1();
It is unclear if the last statement should call the class method C.m1() or the instance method I.m1().

Java 8 default method readability

Java 8 introduces the concept of default methods. Consider the following interface with a default method :
public interface IDefaultMethod {
public abstract void musImplementThisMethod();
public default void mayOrMayNotImplementThisMethod() {
System.out.println(" This method is optional for classes that implement this interface ");
}
}
And a class that implements this interface :
public class DefaultMethodImpl implements IDefaultMethod {
#Override
public void musImplementThisMethod() {
System.out.println("This method must be implementd ");
}
#Override
public void mayOrMayNotImplementThisMethod() {
// TODO Auto-generated method stub
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
}
}
I have a question about the readability of the following call in the mayOrMayNotImplementThisMethod :
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
I understand that the reason for explicitly specifying the interface name in the above call is to avoid confusion in case multiple interfaces implemented by the class have the same method. What I don't understand is the meaning of the super keyword in this context. When we say IDefaultMethod.super, what exactly are we referring to here? Wouldn't IDefaultMethod.mayOrMayNotImplementThisMethod() be more readable than IDefaultMethod.super.mayOrMayNotImplementThisMethod()? Removing the super keyword makes it more readable at the cost of distinguishing between a static or non static method call.
I will try to contribute to the discussion by following my own reasonings about this.
Using Classes
First, let's see how this work with simple Java classes:
class Barney {
void foo() { System.out.println("Barney says foo"); }
}
class Fred extends Barney {
#Override void foo() { super.foo(); }
}
In this case if we invoke the method foo in a Fred instance it will ask for the implementation of the foo method in its super class and execute that one.
Evidently, none of these others would work:
#Override void foo() { foo(); } //means this.foo() so infinite recursion
#Override void foo() { Barney.foo(); } //means a static method
There is a third configuration that we could do:
class Barney {
void foo() { System.out.println("Barney says foo"); }
class Fred extends Barney {
#Override void foo() { Barney.this.foo(); }
}
}
In this case if we invoke foo in a instance of Fred, since this instance would have a bond with its enclosing instance, this invocation would invoke the foo method in the enclosing instance of Barney.
For instance
new Barney().new Fred().foo();
So, the use of Barney.this here is used to navigate between instances in an inner/outer relation.
Using Interfaces
Now let's try to repeat the same ideas with interfaces.
interface Barney {
default void foo() { System.out.println("Barney says foo"); }
}
interface Fred extends Barney {
#Override default void foo() { Barney.super.foo(); }
}
As far as I can tell, this is exactly the same thing as with classes, it is just that in this case since an interface can inherit from more than one interface we simply qualify the super keyword with the name of the interface we are targeting in this case.
The meaning is the same, we want to invoke the "implementation" of the foo method in the super interface explicitly named.
As with classes, the following would not work:
#Override default void foo() { super.foo(); } //can't be sure of which interface
#Override default void foo() { this.foo(); } //infinite recursion
#Override default void foo() { Barney.foo(); } //static method
#Override default void foo() { Barney.this.foo(); } //not an inner class relation
So, the logical choice here is Interface.super.method().
A question here would be whether we cab ever have a use case like Interface.this.method when using interfaces.
Not really, because interfaces represent a static context, therefore there is never a concept like that of inner classes between interfaces. So this is never possible.
interface Barney {
default void foo() { System.out.println("Barney says foo"); }
interface Fred extends Barney {
#Override default void foo() { Barney.this.foo(); }
}
}
Basically, this is not possible because the code above does not mean that an instance of Fred would need to exist within the context of an instance of Barney. This is just a static inner interface and instances of it can exist independently of any instances of the parent interface.
So, that's why this would not be a good choice.
So, as you can see, after all this the use of super kind of makes sense, or at least I hope I have explained myself well enough to convey that idea.
This is simply an extension to default methods of the usual approach to accessing members of superclasses (JLS 15.11):
The form T.super.Identifier refers to the field named Identifier of the lexically enclosing instance corresponding to T, but with that instance viewed as an instance of the superclass of T.
Essentially, there can be ambiguity about which member is being referred to when a class has more than one ancestor (whether because of default methods or just because it has multiple superclasses in a hierarchy). The super keyword is the analog of Outer.this in an inner class; it means that you want to get "this, but the stuff I would see inside the body of that superclass instead of the member inside this subclass".
super refers to a class or interface you inherit from. It is means you want to call a method ignoring the fact it has been overridden.
If you used this you would be referring to this class (or a sub-class) and thus have infinite recursion.
Java 8 interfaces also have static methods.
If you say,
IDefaultMethod.mayOrMayNotImplementThisMethod();
Then it is a way to call static method, which also seems correct as it is similar to how we access static members of class.
For default method, if 'super' is not used then they might have used 'this', which does not make sense as 'this' belongs to class where we are making method call.
My opinion is, you are correct as it does not provide good readability but seems it is as per language design.

Same method with different return types in abstract class and interface

Just extending the question..
Same method in abstract class and interface
Suppose a class implements an interface and extends an abstract class and both have the same method (name+signature), but different return types. Now when i override the method it compiles only when i make the return type same as that of the interface declaration.
Also, what would happen if the method is declared as private or final in the abstract class or the interface?
**On a side note. Mr. Einstein stuck to this question for an abominable amount of time during an interview. Is there a popular scenario where we do this or he was just showing off?
If the method in abstract class is abstract too, you will have to provide its implementation in the first concrete class it extends. Additionally, you will have to provide implementation of interface. If both the methods differ only in return type, the concrete class will have overloaded methods which differ only in return type. And we can't have overloaded methods which differ only in return type, hence the error.
interface io {
public void show();
}
abstract class Demo {
abstract int show();
}
class Test extends Demo implements io {
void show () { //Overloaded method based on return type, Error
}
int show() { //Error
return 1;
}
public static void main (String args[]) {
}
}
No, same method names and parameters, but different return types is not possible in Java. The underlying Java type system is not able* to determine differences between calls to the methods at runtime.
(*I am sure someone will prove me wrong, but most likely the solution is considered bad style anyways.)
Regarding private/final: Since you have to implement those methods, neither the interface method nor the abstract method can be final. Interface methods are public by default. The abstract method can't be private, since it must be visible in the implementing class, otherwise you can never fulfill the method implementation, because your implementing class can't "see" the method.
With Interfaces the methods are abstract and public by default ,
so they cant have any other access specifier and they cant be final
With abstract class , abstract methods can have any access specifier other than private and because they are abstract they cant be final
While overriding , the method signature has to be same ; and covariant(subclass of the declared return type) return types are allowed
A class cannot implement two interfaces that have methods with same name but different return type. It will give compile time error.
Methods inside interface are by default public abstract they don't have any other specifier.
interface A
{
public void a();
}
interface B
{
public int a();
}
class C implements A,B
{
public void a() // error
{
//implementation
}
public int a() // error
{
//implementation
}
public static void main(String args[])
{
}
}

Abstract methods in Java

I want to write an abstract method but the compiler persistently gives this error:
abstract methods cannot have a body
I have a method like this:
public abstract boolean isChanged() {
return smt else...
}
What is wrong here?
Abstract methods means there is no default implementation for it and an implementing class will provide the details.
Essentially, you would have
abstract class AbstractObject {
public abstract void method();
}
class ImplementingObject extends AbstractObject {
public void method() {
doSomething();
}
}
So, it's exactly as the error states: your abstract method can not have a body.
There's a full tutorial on Oracle's site at: http://download.oracle.com/javase/tutorial/java/IandI/abstract.html
The reason you would do something like this is if multiple objects can share some behavior, but not all behavior.
A very simple example would be shapes:
You can have a generic graphic object, which knows how to reposition itself, but the implementing classes will actually draw themselves.
(This is taken from the site I linked above)
abstract class GraphicObject {
int x, y;
...
void moveTo(int newX, int newY) {
...
}
abstract void draw();
abstract void resize();
}
class Circle extends GraphicObject {
void draw() {
...
}
void resize() {
...
}
}
class Rectangle extends GraphicObject {
void draw() {
...
}
void resize() {
...
}
}
If you use the java keyword abstract you cannot provide an implementation.
Sometimes this idea comes from having a background in C++ and mistaking the virtual keyword in C++ as being "almost the same" as the abstract keyword in Java.
In C++ virtual indicates that a method can be overridden and polymorphism will follow, but abstract in Java is not the same thing. In Java abstract is more like a pure virtual method, or one where the implementation must be provided by a subclass. Since Java supports polymorphism without the need to declare it, all methods are virtual from a C++ point of view. So if you want to provide a method that might be overridden, just write it as a "normal" method.
Now to protect a method from being overridden, Java uses the keyword final in coordination with the method declaration to indicate that subclasses cannot override the method.
The error message tells the exact reason: "abstract methods cannot have a body".
They can only be defined in abstract classes and interfaces (interface methods are implicitly abstract!) and the idea is, that the subclass implements the method.
Example:
public abstract class AbstractGreeter {
public abstract String getHelloMessage();
public void sayHello() {
System.out.println(getHelloMessage());
}
}
public class FrenchGreeter extends AbstractGreeter{
// we must implement the abstract method
#Override
public String getHelloMessage() {
return "bonjour";
}
}

super.super.func()? - Java polymorphism

Say that I in Java have 3 classes, wheres the super one has a function named func(), I now make a subclass which overrides this, and a subclass to my subclass, now working on my sub-sub-class how will I call the 'func()' of the sub class, and the superclass?
I tried casting the 'this' "pointer", but Java 'fixes' it at runtime and calls the subsub func().
Edit:
Thanks everyone; 'Skeen is back at the drawing board'.
The best you can do is call super.func() in your subsub class, and have the func() implementation in your subclass also call super.func().
However, ask yourself, if I need knowledge not only of my parents implementation but also my grandparents implementation, do I have a design problem? Quite frankly this is tripping my "Something stinks in the fridge" instinct. You need to re-evaluate why you want to do this.
This isn't possible in Java. And btw. there aren't any pointers in Java.
I would jump on the "something in this design smells funny" train. Normally, you override a method so that it works properly for that specific subclass. If you have code in your parent class that is shared across multiple subclasses, perhaps that code could be moved to a non-overridden method so that it is readily accessible by all children/granchildren/etc.
Could you perhaps flip your design over and use more of a template method approach? (http://en.wikipedia.org/wiki/Template_method_pattern)
The notion behind Template Method is that you have some algorithm in your parent class and you can fill in the pieces that need to be class specific by polymorphic calls into your subclasses. You don't have a ton of detail in your question, but by the sounds of things, I'd really take a good look at your design and see if it makes sense.
Why don't you have func() be not inherited (call it funcBase() or whatever) and then add a wrapper func() function that calls it?
class A{
public void funcBase() {
// Base implementation
}
public void func() {
funcBase();
}
}
class B extends A{
public void func(){
super.func();
}
}
class C extends B{
public void foo(){
super.func(); // Call B's func
funcBase(); // Call A's func
}
}
I have no idea what you're trying to do, but it sounds like your class design is not appropriate for what you want, so you may want separate functions in A instead of trying to sneak your way up the ladder.
This example is the only way to call a "grandparent" super method.
class A{
public void foo(){ System.out.println("Hi"); }
}
class B extends A{
public void foo(){ super(); }
}
class C extends B{
public void foo(){ super(); }
}
This would be a different story if B doesn't override foo().
Another option would be to have a "protected helper" method in the middle class.
class D{
public void foo(){ System.out.println("Hi"); }
}
class E extends D{
public void foo(){ System.out.println("Hello"); }
protected void bar(){ super.foo(); }
}
class F extends E{
public void foo(){ super.bar(); }
}
You can access the superclass methods from within the subclass itself, e.g.
class A {
void foo() {...}
}
class B extends A {
void foo() {...}
void defaultFoo() { super.foo(); }
}
However, you really shouldn't be exposing overridden methods this way, you should write B.foo() in such a way that works fine for A and B. This is where it is a good idea to use super.foo(); like this:
class B extends A {
void foo() {
super.foo(); //call superclass implementation first
... //do stuff specific to B
}
}
Update: In response to your comment on trying to access the implementation 2 levels up, here's a way of doing it.
class A {
void foo() {
defaultFoo();
}
protected void defaultFoo() { ... }
}
class B extends A {
void foo() {...}
}
class C extends B {
void foo() {
defaultFoo();
... //do other stuff
}
}
This is a healthier pattern of coding what you want to do.
You should probably rethink how you are handling your class hierarchy if you need to place a call to a function that is defined two levels up the hierarchy. Consider writing new methods that are implemented by each subclass in a different way.

Categories