I am asking this here because I really don't know how I should Google this. I need a confirmation of something that I probably figured out today. Some days ago I thought that if an object inherits a method of its father it means that it basically "has" the method in its code. But then I asked what if we do this:
class B extends A {
public B() {
}
public int getValue() {
return 2 * super.getValue();
}
}
class C extends B {
public C() {
}
public int getValue(int b) {
return 5 * b;
}
}
And lets say there is a class A that has the getValue() method too. Now an object of class C uses "its" getValue() method (without parameter) that it has inherited from B.
But super.getValue() still refers to class A, even though the method calling it was inherited.
Inheritance does not mean that class C "has" the method in its code, but that it can use it from B, right? super() still refers to the superclass of its "original" class.
Is that insight correct?
Inheritance does not mean that class C "has" the method in its code, but that it can use it from B, right?
Yes.
super() still refers to the superclass of its "original" class.
Yes. You are correct. super always refers to the Parent class of where it is being used. In this case it is being used in B and it's Parent is A. So referring to there.
A sub-class can override any non-private method of its super-class. If it doesn't override them, it inherits the implementation of these methods from its super-class.
Therefore you can say that the sub-class "has" access to all the non-private methods of all of its ancestors. And from a reference to an instance of a sub-class you can invoke any accessible (based on the access modifiers) method of the sub-class or any ancestor of the sub-class.
The super keyword allows you to invoke a method implementation of the super-class from the sub-class. This way you can override the implementation of a method of the super-class, but still execute the implementation of the super-class too.
In your class B :
This implementation overrides the getValue() of A :
public int getValue() {
return 5;
}
While this implementation overrides the getValue() of A, but still uses its logic :
public int getValue() {
return 2 * super.getValue();
}
Of course, you can't implement both in the same class, since they have the same signature.
Related
In the book Java: The complete reference
// Demonstrate when constructors are called.
// Create a super class.
class A {
A() {
System.out.println("Inside A's constructor.");
}
}
// Create a subclass by extending class A.
class B extends A {
B() {
System.out.println("Inside B's constructor.");
}
}
// Create another subclass by extending B.
class C extends B {
C() {
System.out.println("Inside C's constructor.");
}
}
class CallingCons {
public static void main(String args[]) {
C c = new C();
}
}
Output:
Inside A’s constructor
Inside B’s constructor
Inside C’s constructor
It is demonstrating how the constructor of a subclass is called. But why are constructors of the super class called in the absence of a super() constructor.
Why did the Java Language designers consider it necessary to do so?
As others have pointed out, if you don't start your constructor with a super(...) call, the compiler will put in a call to super() for you.
As to the why, you have to start with remembering what a constructor is for in the first place: initializing the object. What does that mean, specifically? In practice, it means assigning values to the object's fields, and establishing invariants.
Without a call to super(), the B and A classes wouldn't have a chance to do that for whatever fields they contain. And you can't even have the C() constructor do it for them, if those fields are private, since private fields aren't accessible outside your class (not even your super class's fields are accessible). Even if you could, it wouldn't be a good idea; it would also break encapsulation. For instance, imagine having to change your code if a super class -- possibly a complex one whose internals you're not an expert in -- suddenly decided to change its implementation details.
To illustrate this, consider a very simple set of classes:
public class Super {
private final String name;
Super() {
name = "default";
}
public String name() {
return name.toUpperCase();
}
}
public class Sub extends Super {
public Sub() {
// don't do anything
}
}
When you instantiate Sub, it will start out by calling Super's constructor. If it didn't, the name field would be null (the default value for reference types). But the name() method doesn't check for null; it assumes that the reference is non-null, because the constructor establishes that invariant. So, in our pseudo-Java that doesn't call the super constructor, Super.name has to get a bit more complicated -- it has to check for name == null.
You can imagine that as the classes gain more fields, with more interesting invariants, this toy example can become more and more complicated. Forcing you to call the super constructor -- either explicitly or implicitly -- lets the authors of that super class establish their invariants, resulting in simpler, more maintainable code.
Every constructor calls its superclass constructor. super() call take place as the first line in the constructor. From javadoc:
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
more here
Because it says so in the Java Language Specification.
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
Even it has a role with Abstract classes also. we can't initialize object of abstract class. But Child class of Abstract class calls the super() method by default. So abstract class constructor can initialize its instance variables.
for example:
public abstract class TestA {
private int a;
public TestA()
{
a=10;
}
public int displayA()
{
return a;
}
abstract void display();
}
public class TestB extends TestA{
#Override
void display() {
System.out.println("this is class B");
}
}
package Abstract;
public class TestMain {
public static void main(String[] args) {
TestA obj= new TestB();
System.out.println(obj.displayA());
}
}
Output is : 10
Here you can see, when we initiating object of class TestB , by default super constructor is calling and TestA's constructor is assigning the value of a. If super will not be called by default we can't assign instance variables of abstract class.
Inheritance is basically inheriting all the properties of your parent class. So if a sub class constructor is called, it should definitely and by default inherit all its parent class properties also. In the following code, all the properties of class A should be made available in class B also, so if I just call B's constructor, all the class A's properties(except private) are also initialized and made available, meaning B has inherited A's properties
class A {
protected int a;
A() {
a=12;
System.out.println("Inside A's constructor.");
}
}
class B extends A {
B() {
System.out.println("Inside B's constructor.");
System.out.println(a);
}
}
public class ConstructorInheritance {
public static void main(String args[]) {
B b=new B();
}
}
output:
Inside A's constructor.
Inside B's constructor.
12
Imagine class C accessing an unitialized variable of class B or A. Implicitly calling constructors of class B-->class A makes sure that you are always accessing initialized variables of inherited classes(A or B)
"The Java programming language" says "A constructor in subclass can initialize its individual state, however, as keeping contract, only super class knows how to initialize super class's state".
Thus, constructor of super class have to be called. There is sequence how the constructor processed:
Call super class constructor
Initialize fields with initializers and initialization blocks
Execute body of the constructor
For more details, have a look of the book to section "3.2".
I have a abstract superclass with some implemented methods.
Is it possible to hide methods from this superclass in an subclass inheriting from this superclass? I don't want to have some methods visible from the superclass in some of the subclasses. Last but not least, is it possible to change the number of arguments for a method in the subclass which has the same name in the superclass?
Let's say we have a method public void test(int a, int b) in the superclass but now I want a method public void test(int a) in the subclass which calls the superclass function and the method from the superclass not visible anymore.
Is it possible to hide methods from this superclass in an subclass inheriting from this superclass?
If you make the method private in the super class, it won't be visible in the subclass (or to any one else).
If you need the method in the base class to be public however, there is no way of hiding it in the subclass by for instance overriding it with a private implementation. (You can't "reduce visibility", i.e. go from for instance public or protected to private in a subclass.)
The best workaround is probably to override the method and throw for a runtime exception such as UnsupportedOperationException.
is it possible to change the number of arguments for a method in the subclass which has the same name in the superclass?
No, you can't change the signature. You can create another method with the same name and a different number of arguments but this would be a different (overloaded) method and the method in the base class would still be visible.
You can't completely hide a method from superclass, it's always possible to call, e.g.
MyBase o = new MyClass();
o.test(1, 2);
However, you can override the method in a specific way:
class MySuper {
public void test(int a, int b) {; }
}
class MyClass extends MySuper {
#Deprecated
#Override
public void test(int a, int b) {
throw new UnsupportedOperationException("Do not call this method, call test(int a) instead!");
}
public void test(int a) { ; }
}
No you cannot hide a public method in a child, for instance by making the method private there.
The reason is that having an instance of the child class, you may always cast it to the base class, and call the method there.
So this behaviour is logical. Either redesign the class hierarchy or create a new class if this is becoming a too ugly API.
You may however override the method and
/**
* Use <code>test(a)</code> instead.
* #param a.
* #param b.
*/
#Deprecated
#Override
public void test(int a, int b) {
throw new UnsupportedOperationException("Use test(int) instead.");
}
public void test(int a) { // Overloaded method
int b = ...;
super.test(a, b);
}
Overloading a method is possible: same name, different parameter types.
Java doesn't support reducing visibility.
There is a way to do something like this but it's complex:
You need to create an interface for the parent type. This interface doesn't need to have methods.
You create another, new type Delegate which implements the method public void test(int a, int b)
You delete the current parent type.
You create two new types which implement the interface. One delegates the call test(a,b) to Delegate and the other one creates a new method test(a) which eventually uses a Delegate instance.
So the type which implements the old code is never visible to the outside world (it could be a package private class).
Are fields only inherited "one level up"?
By that I mean that if I have a Superclass to a Class, which then has a Subclass, and the Superclass has a field, the Class will inherit it and the Subclass won't. Is this correct?
And if it is, is there a way to make the Subclass automatically inherit the field from the Superclass given that, as I understand it, there's no way to inherit from two classes at once?
Thank you to anyone who takes the time to answer. I realize my question may be impractical and in reality you'd probably just override the field or something, but I'm not trying to do anything specific, just trying to learn how Java works. Thank you.
Here's my code:
public class SuperClass {
protected int entero;
protected void method(){
entero=1;
}
public class SubClass extends Class {
public SubClass(){}
}
public class Class extends SuperClass {
public Class(){}
}
public static void main(String[] args){
Class object= new Class();
SubClass subobject= new SubClass();
/*This is where I get an error, why?*/
subobject.entero=2;
/*This one is fine*/
object.entero=2;
object.method();
System.out.println(object.entero);
}
Any class B than extends a class A, will inherit A's fields. If a class C extends B, C will inherit all non-private instance fields and methods from A and B, ie transitivity holds.
If a field is private, then one cannot directly change it from a subclass; however, you can get around this by using setter/getter methods.
If a field is protected, then a subclass has direct access to it.
EDIT 1:
In a comment you say that the field is protected, but you still can't access it from a subclass. The only thing I can think of is that you have a situation like this:
class A
{
protected int x;
}
class B extends A
{
private int x;
}
class C extends B
{
private int z = x;
}
This would NOT work because by declaring x again in B, you are hiding the x field from A. So, now C sees x as B's private variable x, which you do not have access to.
EDIT 2:
I'm not going to remove the above edit, because it's informative, but now that you posted your code, it's because your SubClass does not actually extend anything (this was later fixed in an edit).
Inheritance in Java is transitive.
If your classes are Superclass < Class < Subclass, then Subclass inherits all the non-private instance fields and methods provided by Superclass not overridden or hidden by Class or Subclass.
One level of inheritance is specified by the Java Language Specification, section 8.4.8: Inheritance, Overriding and Hiding:
A class C inherits from its direct superclass and direct superinterfaces all abstract
and non-abstract methods of the superclass and superinterfaces that are public,
protected, or declared with default access in the same package as C, and are neither
overridden (§8.4.8.1) nor hidden (§8.4.8.2) by a declaration in the class.
If you have classes that are:
public class SuperClass {
public void methodName() {}
//SuperClass's stuff
}
public class MidClass extends SuperClass {
//MidClass's stuff
}
public class SubClass extends MidClass {
//SubClass's Stuff
}
Then it is perfectly valid to have in your main method:
SubClass sc = new SubClass();
sc.methodName();
public interface ICalculator {
public double multi(double a, double b);
public int add(int a, int b);
public int sub(int a, int b);
}
public class Calculator extends ICalculator {
protected int add(double a, double b) {
return a+b;
}
public double sub(int zahl1, int zahl2 ) {
return a*b;
}
}
why i can't use in the class Calculator a protected method ?
My answer is that "protected" is it useful in the same class and in the subclasses . Well couldn't i also think that a method in an implemented class from Interface is also inherited, like subclasses.
You cannot add more restriction to the method you override in the sub class.In the same way, you cannot add more restriction to the method you implement from an interface.
Now, since methods defined in an interface is by default - public (Yes, you don't need to write it explicitly), so you cannot make your method protected in implementing class.
The reason is straight, when you are working with polymorphism, you can instantiate your implementing class and store its reference in the interface type.
ICalculator calc = new Calculator(); //valid
calc.add(1, 2); // Compiler sees ICalculator method.
Now, when you invoke the add method using ICalculator reference, compiler only sees the method defined in ICalculator, and approves access accordingly. But at runtime, the actual method invoked is form Calculator class, and what happens now, if that method is actually invoked from a different package and non-subclass -- BOOOOOM, it crashes at runtime.
That is why it's not allowed.
Same concept applies when you are adding an extra checked exception. Compiler will again stop you. But yes, you can add an extra Unchecked Exceptionthough, because those are simply ignored by the Compiler.
From the Java Language Specification, §9.4:
Every method declaration in the body of an interface is implicitly public (§6.6).
Every method declaration in the body of an interface is implicitly abstract, so its body is always represented by a semicolon, not a block.
It is permitted, but discouraged as a matter of style, to redundantly specify the public and/or abstract modifier for a method declared in an interface.
And from the JLS, §8.4.8.3:
The access modifier (§6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method...
Put the rules from those two sections together and the conclusion is that any method that is part of an interface implementation must be public.
Interfaces in Java are usage-contract of a class for its clients. So all their methods are public, and you can not apply more restriction on overridden methods.
Given a few classes/interfaces.
public interface A {
public int doSomthing(int x);
}
public class B implements A {
int doSomthing(int x){
//actually do something
};
}
public class C extends B {
//does some specific implementations of what B does
// but does NOT override "int doSomething(int)"
}
How in a code using implementation C (or any subClass of C) may I determine (programatically) that B was the class implementing int doSomething(int).
Or if any of B's subclasses (lets say D which extends C) overrid "int doSomething(int)" how, when working with E (which extends D, yeah ... this is one large family of classes) may I define first parent that implemented "int doSomething(int)" ?
Thank you all in advance :)
You can do that using reflection, i.e. you start at the class the object has and check whether that class defines the method which is identified by the methodname and parameter types. If the class doesn't define that method you get its super class and check this, until you hit Object in which case the method isn't available at all.
For public methods, it's easier since Java has already a built-in method for this:
Class<?> mostSpecificImplementor =
yourObject.getClass().getMethod( "doSomthing", int.class ).getDeclaringClass();
Note that this only works for public methods, otherwise you'd have to search up the class hierarchy yourself (use getDeclaredMethod(...) in this case).