Here's what i remembered:
In C++, if derived class defines a member function with the same name, but different signature (parameter etc) than the base class, it'll 'hide' the corresponding member function in base. e.g.
class Base {
public:
void virtual f(double x);
};
class Derived : public Base {
public:
void f(char c);
};
int main()
{
Derived* d = new Derived();
Base* b = d;
b->f(65.3); // call f(double x)
d->f(65.3); // call f(char c)
delete d;
return 0;
}
correct me if i am wrong, but i think in C++ by saying 'hide', it also means Derived class can not see 'f(double x)', or in other words, Derived do not have 'f(double x)' as its inherited member function from Base, correct?
In Java tutorial, 'hide' actually means something else (for static class method), whereas for instance method, you can overload the method inherited from base. Looking at this example: Using inherited overloaded methods
public class ClassA {
public void method(Number n) {
System.out.println("ClassA: " + n + " " + n.getClass());
}
}
public class ClassB extends ClassA {
public void method(Integer d) {
System.out.println("ClassB: " + d + " " + d.getClass());
}
}
ClassA a = new ClassB();
a.method(3);
In C++ type of thinking, i would get the same result that 'method(Number n)' from Class A is called, based on 'dynamic binding' and 'hiding' idea in C++, but:
I am still not sure how to explain it in Java. The link itself explains using 'method signature is chosen at compile time' and 'it is actually calling from Class B'; but in C++ thinking, the former is OK, but i do not think it's calling from Class B, it should be calling from Class A, right?
In Using inherited overloaded methods and Java tutorial, 'Class B' is allowed to overload function from 'Class A', and 'Class B' actually can see both 'method(Number n)' and 'method(Integer d)'. So C++ and Java are treating overloading differently, right? And why is that? Say in the C++ example, if Derived also allow overloading, 'd->f(65.3)' would call 'f(double x)', not 'f(char c)'.
Thanks,
In C++ every thing is static for non-virtual functions, so for non-virtual functions you don't have dynamic-binding. And hiding do not remove function from inheritance. It's something like this:
When you define method M as: void M(int) then compiler implement a function internally name Base::M as void Base::M( Base* this, int ). Now this function is implemented somewhere in code and can't removed and you can call it as long as you be able to provide a this (actually you can call it without even having this). So in Child I can call Base::M(0); and C++ convert this from Child* to Base* and call M. When you define a function with its name correspond to the name of base class you tell the compiler that I prefer to use that name in my class for a new method or property! But you don't remove any thing and you can use using to bring old definition of M to Child:
struct Base {
void f( int ) {}
};
struct Child : Base {
void f( char* ) {}
using Base::f; // Bring Base::f to this class, so I have f(char*), f(int)
};
And beside that you can call f(int) without even use of using.
// In the Child class
void test() {
Base::f('c'); // Call Base::f(char)
}
// Outside of class
Child c;
((Base*)&c)->f('1');
This is not how I would expect C++ to behave. Rather than hiding the base class method, I would expect the subclass to simply overload the method because the parameters are different. Thus, the compiler will know which method to use when you call b->f() because there's only one available, but it has to work out which one to use when you call d->f() based in your parameter type. If it can't then at compile time you will be forced to use a cast. With your example it should recognise the decimal point and use double instead if char.
Related
I have problems understanding the behaviour of this piece of code.
a is defined as an A, c is defined as a C.
Then, at the end of the public class, a = c.
When a calls the display() method it reaches the C version of it.
But when a calls the f() it only reaches the A version, despite the fact that the first arguments (byte and long) are more compliant with long than float.
It's an exercice from a book, but explanation is scarce, or inexistent.
class A{
public void display(){
System.out.println("I am an A ");
}
public void f(double x){
System.out.println("A.f(double = " + x + ") ");
}
}
class C extends A{
public void display(){
System.out.println("I am a C ");}
public void f(long q){
System.out.println("C.f(long = " + q + ") ");}
}
public class PolySurStack{
public static void main(String Args[]){
byte bb =1; long q = 4; float x = 5.f;
System.out.println(" ** A **");
A a = new A(); a.display();
a.f(bb); a.f(x);
System.out.println();
System.out.println(" ** C **");
C c = new C(); c.display();
c.f(bb); c.f(q); c.f(x);
System.out.println();
a = c; a.display();
a.f(bb); a.f(q); a.f(x);
}
}
When you call a.f(bb) or a.f(q) or a.f(x), the only method signatures the compiler can choose from are those defined in class A (or any super class of A), since a is a reference variable of type A.
Therefore, only public void f(double x) is considered. In order for public void f(long q) to be a candidate for overload resolution, you'd have to cast a to type C before calling f(), since only class C defines a method with that signature.
The important thing to understand is that method overloading resolution takes place in compile time. Only the compile time type of the reference variable for which you call the method determines which method signatures are candidates for method overloading resolution, as well as which candidate will be chosen.
I just found this on another forum :
Overloading :(same function name but different signature)
Two or more methods having the same name with different arugment in same class is known as Overloading.
Overloading is used when you want to extend the functionality.
Overloading is known as compile time polymorphism
Overriding :(same function name but same signature)
Two or more methods having the same method name and same arugment in parent class and child class in known as overriding.
Overriding is used when you want to reuse the existing functionlity.
Overriding is known as run time polymorphism
So the answer to my question seems to be that overriding resolution (like for display() )occurs at run time (here after a = c) while overloading resolution (like for f() ) occurs at compilation time, when a is Still an A.
I think.
I also found this page : https://beginnersbook.com/2013/04/runtime-compile-time-polymorphism/
to be clear and highly relevant to this topic.
The method selected by the compiler depends on the declared type, not on the runtime type.
The first series that declares as variable A can only invoke A methods (whatever the runtime type instantiated as A derives only of Object) :
A a = new A();
a.f(bb); a.f(x);
For the second series, the compiler binds the methods with the most specific parameter matching to the invocation since C is a A and so the compiler can bind any public methods of these here :
C c = new C();
c.f(bb); c.f(q); c.f(x);
But in the last chunk of code that probably questions yourself, a refers to C as runtime object but to A as declared type :
A a = new A();
// ...
a = c;
a.f(bb); a.f(q); a.f(x);
So only methods defined in A may be invoked.
I'll try to clarify the answer of #eran a bit so you can understand it.
A subclass has all the methods of its superclass, and then perhaps some more in addition to them. You have a variable of type A, in which you store an object of type C. C has all the methods that are defined in class A, and also an additional method that is f(long q). A is unaware of this new method, so since you store the object in a variable of A, you can't call f(long q).
You can however call display() because it is defined in A, but it will still be the C object that executes it.
Is there some object oriented thing that you can call some methods from certain classes, but not all of them? Is there something like that which is similiar to protected?
Say you have a method void foo() and you want it to be available to the programmer in a few types of classes (perhaps something like using Type variables (to specify: T type). Now, perhaps is there some way, without inheriting the class with foo() in it, or making an interface, to specify which classes or types of classes have access to that method?
I would guess this could be like multiple-inheritance and polymorphism? But I still want only the class and certain classes to access the method without changing the visibility of the method. I want the visibility to be class-specific.
Here is an example:
class A sees foo() as private, but only that class sees it as private.
class B sees foo() as public/protected, but only that class sees it as public.
The method type would be default.
I guess what is easier to ask and answer to is: "Is there class-specific visibility?"
There is something like you are asking for in C++, it is called friend classes. Nevertheless, that concept is not supported by Java:
'Friends' equivalent for Java?
A second option is to use code reflection to access a class private members but it isn't such a clean solution and only works for protected elements:
public class C1 {
public C1()
{
x = "Hello Word!";
}
protected String x;
}
At a different class's method:
String val = (String)obj.getClass().getDeclaredField("x").get(obj);
System.out.println("val: " + val);
EDIT: After making a little bit of research I found it is possible even to access private members:
Field field = obj.getClass().getDeclaredField("x");
field.setAccessible(true);
String val = (String)field.get(obj);
field.setAccessible(false);
No, there's nothing like that in Java.
The closest you've got is putting classes within the same package, at which point they have access to any members which don't specify any access modifier. You can't specify particular classes though.
Another option which is appropriate in some cases is to use nested classes:
class Outer {
private static class Inner {
}
}
Here Outer and Inner have access to each other's private members.
Access Levels
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N
thats your lot, there are not any other access modifiers.
With a little sleight of hand you can make one class seem to be two different classes:
// An interface.
interface A {
public void a ();
}
// Another interface.
interface B {
public void b ();
}
// Deliberately NOT stating we implement either A or B but actually we implement both.
class C {
public void a () {
}
public void b () {
}
}
// Pick either implementation from C and tell the world about it.
class D extends C implements A {
// Do nothing - already done by C.
}
class E extends C implements B {
// Do nothing - already done by C.
}
public void test() {
A d = new D();
B e = new E();
}
Here D and E are actually identically functioned objects because they are both actually Cs. However, as they are created they are made to seem to be A or B which are two different interfaces.
Unfortunately we cannot hide the fact that they both extend C but a little further sleight of hand and we can do that too with a Factory.
// Hide the guts of it all in a factory.
static class Factory {
// Make sure you MUST use the factory methods.
private Factory () {
}
// Construct an A.
public static A newA () {
return new D();
}
// Construct a B.
public static B newB () {
return new E();
}
}
If I have the following code in Java:
class A {
public int add(int a , int b) {
return (a+b);
}
}
class B extends A {
public float add(float a , float b) {
return (a+b);
}
In this particular case the sub-class isn't exactly overriding the base class's add function as they have different signatures and the concept of overloading occurs only if they are in the same scope. So, is the function add(float , float) in the sub-class B treated as an entirely new function and the concept of overloading and overriding is not applicable to it? And does it use 'Static binding' or 'Dynamic Binding'?
Method add in class b is an overload of add in class a. Not an override. An override would just be a different implementation of the original add method.
In brief, yes. To override, you need to replicate the complete method signature, which includes the method name, parameters and return types. From the tutorial
An instance method in a subclass with the same signature (name, plus
the number and the type of its parameters) and return type as an
instance method in the superclass overrides the superclass's method.
You might want to consider the #Override annotation, which will trigger a compiler error if you don't successfully overrride a method.
In this particular instance, it perhaps looks like you don't need overriding so much as some solution including generics. So you could instantiate a class a<Integer> and a similar class a<Float>
In that case you are not overriding the method, since the signatures are different.
But there is overloading in class b, since you have two methods with the same name but different parameters (one if class a, and the other one in class b)
Hope it helps.
There can be a method that is not overridden but overloaded in the subclass. Here the subclass has two add() methods. The version which accepts int arguments(not overridden), and the overloaded method add() which accepts float arguments.
I think in this particular case neither overloading nor overriding occurs, because return type must be same in case overloading and overriding, so neither static binding nor dynamic binding happens in this case.
method overloading is not possible in case of different return type, because compiler can't figure that which method he need to call.
I know it's late answer but i think it's important question need to be answered for beginners.
One key point in overloading is it works in inheritance.
Next is either it's Static binding or Dynamic binding.
It is Static Binding So, why?
Static Binding
Static binding in Java occurs during Compile time.
private, final and static methods and variables uses static binding and bonded by compiler.
Static binding uses Type (class in Java) information for binding.
Dynamic Binding
Dynamic binding occurs during Runtime.
Dynamic methods bonded during runtime based upon runtime object.
Dynamic binding uses Object to resolve binding.
But the important part is here
Overloaded methods are bonded using static binding while overridden methods are bonded using dynamic binding at runtime.
Java compiler determines correct version of the overloaded method to be executed at compile time based upon the type of argument used to call the method and parameters of the overloaded methods of both these classes receive the values of arguments used in call and executes the overloaded method.
B a=new B();
a.add(4, 5);
a.add(4.0f, 5.0f);
So if you will create reference of type B then it will search for proper argument type
and for above code it will execute both methods.
A a=new B();
a.add(4, 5);
a.add(4.0f, 5.0f);
but for above code it will give compile time error for float arguments.
Hope it clears all doubts.
First things first
Is it method overriding ?
No , since to override a method you need to replicate the complete method signature as pointed out in Brian Agnew's answer and as I explain below.
Is it overloading ?
Yes , Method "add" has an overloaded implementation in Class B.
Consider the following code:
class C{
public static void main(String args[]){
B a = new B();
a.add(2 , 3);
a.add(2.0 , 3.0);
}
}
class A {
public int add(int a , int b) {
System.out.print("INT ");
return a + b;
}
}
class B extends A {
public double add(double a , double b) {
System.out.print("Double ");
return a + b;
}
}
OUTPUT : INT Double
So , the method in Class B in your code overloads the add method that it inherits from its parent
Does it use Static Binding or Dynamic Binding ?
This is what makes me conclude that OP is confused.It is static binding because it is a overloaded function. The only way to think of dynamic binding would have been in below scenario
class C{
public static void main(String args[]){
A a = new B();
a.add(2.0 , 3.0);
}
}
class A {
public int add(int a , int b) {
System.out.println("A : INT");
return a + b;
}
}
class B extends A {
public int add(int a , int b) {
System.out.println("B : INT");
return a + b;
}
public double add(double a , double b) {
System.out.println("Double");
return a + b;
}
}
Output : B : INT
Here , the parent class A has a contract that says , "I have an add behaviour for ints" . class B inherits this add behaviour and makes it more specific and at the same time also provides a new behaviour where it can add doubles.
But class A has "no knowledge of this behaviour".
So an object of class A "cannot" add doubles. To do that you need a more specific type of A object i.e. a B object.
The method add() in class A is also available to class B by inheritance, therefore the method is overloaded in class by changing the data type from int, int to float, float.
The concept of Overloading comes in play if and only if the functions are in the same scope or class.
cz if this is the case of method overloading then for same method signature or same argument type the compiler gets confuse and must give compile time error .
but in the above program in class B if you pass the same argument in same order then according to overloading it must give error but it is not happening u can check it i already have.
It is the case of inheritance where through object reference if you call any method then the compiler will check it in child class ,if its not there then it will look into parent class that the above program is all about.
hope this is helpfull.
I know how to overload a method, and how to override a method. But is that possible to overload AND override a method at the same time? If yes, please give an example.
Overloading and overriding are complementary things, overloading means the same method name but different parameters, and overriding means the same method name in a subclass with the same parameters. So its not possible for overloading and overriding to happen at the same time because overloading implies different parameters.
Examples:
class A {
public void doSth() { /// }
}
class B extends A {
public void doSth() { /* method overriden */ }
public void doSth(String b) { /* method overloaded */ }
}
Cheers!
overloading and overloading are just abstractions. Overloading just means the compiler uses the name in conjunction with the types and number of parameters for addressing what function to call. In reality overloading a method is no different than naming it something different because the key the compiler uses to look up the function is a combination of name and parameter list.
Overriding is kind of the same principle except the compiler can address the overriden function with the super keyword.
So can you override an overloaded function? Yes, since the overloaded method is a completely different method in the eyes of the compiler.
It depends what you mean. A method can be an override for an overloaded method in a superclass. And you can overload a method that you are simultaneously overriding using another method.
However, you cannot have one method that is both a new overload and an override. For a method to be an override, another method with the same signature must already exist in the superclass ... and that means that this method cannot be a new override.
Yes it is possible, you can overload and override a function in the same class but you would not be able to overload a function in two different classes as it is logically not possible.
#include <bits/stdc++.h>
using namespace std;
class Base {
public:
void print()
{
cout << "Base Function" << endl;
}
void print(string name) //Overloaded Function
{
cout << "Base Function : " <<name<< endl;
}
};
class Derived : public Base {
public:
void print()
{
cout << "Derived Function" << endl;
}
void print(string name) //Overloaded Function
{
cout << "Derived Function : "<<name<< endl;
}
};
int main() {
Derived derived1, derived2;
//accesses the print function in derived class
derived1.print();
//accesses the overloaded print function in derived class
derived1.print("Gitanshu");
//accesses the print function in base class
derived2.Base::print();
//accesses the overloaded print function in base class
derived2.Base::print("Gitanshu");
return 0;
}
Output:
Derived Function
Derived Function : Gitanshu
Base Function
Base Function : Gitanshu
I answered it using C++, The same would apply in Java as well.
I have two classes A and B while B is a subtype of A:
public class A {
private String stringVar;
public A() {
stringVar = "";
}
public String getStringVar() {
return stringVar;
}
public void setStringVar(String str) {
this.stringVar = str;
}
#Override
public String toString() {
return getStringVar();
}
}
Class B:
public class B extends A {
private int intVar;
public B() {
intVar = 0;
}
public int getIntVar() {
return intVar;
}
public void setIntVar(int intVar) {
this.intVar = intVar;
}
#Override
public String toString() {
return super.toString() + " " + getIntVar();
}
}
As you can see in the following main method I assign the b to a. Now "a" can't invoke b's methods which is clear, because I'm using an instance of type A now. But it behaves like a B when toString is invoked. Curious, I would have expected toString of a. Why is this so?
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
b.setIntVar(200);
b.setStringVar("foo");
a = b;
System.out.println(a);
}
}
Because a points to the implementation of B.
And is declared as A.
So behavior of B. And methods visible of A.
To use B methods do like this
((B) a).getIntVar();
Think of it like this
Object o = new FancyObject();
When compiling this only Objects methods will be accepted even though it's a FancyObjcet with lots of methods.
To use the methods of FancyObject on o do like this.
Object o = new FancyObject();
(FancyObject o).fancyMethod();
Quote "because I'm using an instance of type A now" you are still using an instance of type B. You can see it like you have upcasted b but it's the same instance.
Picture cross linked from another site with credits in the picture, if this is against the rules then somebody is free to edit this part of my answer.
This is nature of inheritance / polymorphism and overriding methods.
Overrided methods will be determined in runtime based on objects real type and not based on reference type.
Therefore a.toString() is actually b.toString() because it is determined in runtime.
http://download.oracle.com/javase/tutorial/java/IandI/override.html
The concept you need to understand is the difference between References and Objects.
a is a reference (a local variable in this case) that points first to an Object of type A and then to an Object of type B.
The compiler knows that it must be of type A (or a subtype thereof), so it can safely call all methods A defines, but they will be called on the actual Object, not on the original Type of a.
This is polymorphism: The object that a holds has static type A, but it is still an Object of dynamic type B. Dynamic dispatch therefore chooses the overridden toString() defined in B.
That's exactly how Java's runtime polymorphism works. All that matters is the actual type at runtime. What you have done is take a reference to an A and point it at an instance of B. You have changed the type of the thing that a points to.
Try
a = (A)b;
No, B Overrides the toString method of A, so if an object is an instance of B, when you call its toString method, you get whatever method that instance has. In general, if you have an object and call its methods, the method called is the one that is in the instance, not in the variable type. The only exception is static methods.
In C++, this is not the case. The method called is the one of the variable type, if one exists, unless you explicitly select the above described behavior by making a method virtual.
That is called runtime polymorphism in OOP.