Using this and super in Java - java

I have the following code snippet that attempts to use this and super.
class SuperClass
{
public final int x=10;
public final String s="super";
public String notOverridden()
{
return "Inside super";
}
public String overrriden()
{
return "Inside super";
}
}
final class SubClass extends SuperClass
{
private final int y=15;
private final String s="sub"; //Shadowed member.
#Override
public String overrriden()
{
return "Inside sub";
}
public void test()
{
System.out.println(super.notOverridden());
System.out.println(this.notOverridden());
System.out.println(this.overrriden());
System.out.println(super.overrriden());
System.out.println(this.s);
System.out.println(super.s);
System.out.println(this.x);
System.out.println(super.x);
System.out.println(this.y);
}
}
public final class Test
{
public static void main(String[] args)
{
SubClass subClass=new SubClass();
subClass.test();
}
}
In this simplest of Java code, the statements that redirect the output to the console inside the method test() within the class SubClass display the following output.
Inside super
Inside super
Inside sub
Inside super
sub
super
10
10
15
So, it appears that there is no difference between this and super, when they are used to access methods which are not overridden in its subclass(es) and in case of variables, when they are not shadowed in its subclass(es).
Both of them tend to point to super class members. There is however, an obvious difference, if such is not a case.
Are they same, when methods are not overridden or variables are not shadowed in respective subclasses?

So, it appears that there is no difference between this and super,
when they are used to access methods which are not overridden in
its subclass(es) and in case of variables, when they are not
shadowed in its subclass(es).
There is a difference. If you override methods in third class, and call test from it, you will see, that super still calls implementations of SuperClass. And this will call new implementations (overridden).
Addition:
this.method() usage implies the method belongs to instance of the object. So the last implementation will be used (with exception of private methods).
super.method() usage implies method of the instance, but implemented before the current class (super, or super.super etc).

Yes, they are the same. notOverridden methods and not shadowed variables are inherited by subclass.
To better understand this, knowing how object is located in memory is helpful. For example in the figure below. Assume it's an object of a subclass. The blue area is what it inherits from its parent, and the yellow area is what is defined by itself. The method has the similar design except that it uses a Vtable.
Child object has the same memory layout as parent objects, except that it needs more space to place the newly added fields. The benefit of this layout is that a pointer of parent type pointing at a subclass object still sees the parent object at the beginning.

Related

why cant subclass objects hold super class constructor

Can anybody explain me what is the reason for a sub class object is incapable of holding a super class constructor?
class Alpha
{
String getType1()
{
return "alpha";
}
}
class Beta extends Alpha
{
String getType1()
{
return "beta";
}
String acc()
{
return "acc";
}
}
public static void main(String[] args)
{
Alpha a1=new Beta();
System.out.println(a1.getType1());
}
Here the output is "beta"; but object a1 doesnt have the visibility to acc()?
Nothing surprising here:
System.out.println(a1.getType1());
You are calling a method that is defined in the super class; and overridden in the a subclass. You create an instance of the subclass; and the method that gets executed ... is the overridden version.
The fact that Beta contains another method which is not at all used in your example anyway doesn't come into play here at all. And even if getType1() would be calling acc() - that would still work. That is the essence of of polymorphism!
And just to be precise: none of the methods you have in your classes is a constructor!
i just found the answer here we need to know that when we create beta() internally it will call all its super class default constructors hence the JVM knows that there is more than one existing class but when i declare and initialze like:
Alpha a1=new Beta();
eventhough the JVM knows that beta class is existing but your restricting your access of a1 by saying it is of the type Alpha class hence it cannot access your subclass methods.
When you create a object of child class making reference to its parent class as you did, you only have visible to those methods which belongs to the parent class. but if you want to call the child method using reference of parent class then you have to declare the body of the method in parent class which you have in child class. then it will be visible and this concept is called method overriding.
If you don't need to create the object of your super class then you can declare class as abstract and then you can simply put that method as abstract keyword shown as below.
abstract class Alpha
{
String getType1()
{
return "alpha";
}
abstract String acc();
}
class Beta extends Alpha
{
String getType1()
{
return "beta";
}
#Overriding
String acc()
{
return "acc";
}
}
public static void main(String[] args)
{
Alpha a1=new Beta();
System.out.println(a1.getType1());
}
Child classes are privileged to access to default constructor of parent class until unless you have restricted it with private access modifier.
Your cases is an example of method overloading. Actual call to overloaded method is resolved at run time. Which method will be called, depends on the concrete object not type of object. Here your reference is of type Alpha but the object is of Type Beta. So method getType1() here will print beta which is correct behavior.

What's the difference between override and hidden in java?

I searched a lot. The difference between them is that override is for the instance method and hidden is for the static method. And the hidden is in fact the redefinition of the method. But I still don't get it.If redefinition means that the static method of parent still exists in the subclass, it is just we can't see it? Or why we call it hidden but not any other words? But if it exists, I can't find a way to call the method again. To be honest from a function level I can't find why they are different. Can some one explain it from a deeper level such as memory?
Static members(methods and variables) will not be present in the sub class(Child class) object which inherit them but they'll be present as a single copy in the memory.
Static members can be accessed by the class name of both Super class and sub class but they are not physically present in the object of these classes.
Where as when you inherit non-static members, Sub class object in memory will contain both inherited methods as well as the methods of its own. So when you try to write a similar method here, super class method will be overridden. On the other hand as static methods does not participate in inheritance, any similar method you write that is present in super class, new method will run every-time it is asked for. Parent class method is just hidden but not overridden!
From JLS 8.4.8.2, example 8.4.8.2-1 shows us that a hidden method binds to the type of the reference (Super), while an overriden method binds to the type of Object (Sub).
class Super {
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super {
static String greeting() { return "Hello"; }
String name() { return "Dick"; }
}
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name());
}
}
Output:
Goodnight, Dick
If you call Superclass.staticMethod() you will get the method as defined on the superclass, regardless of any hiding taking place in subclasses. On the other hand, if you call ((Superclass)subObj).instanceMethod() you'll still be calling the method as it is overridden in the subclass.

Use of 'super' keyword when accessing non-overridden superclass methods

I'm trying to get the hang of inheritance in Java and have learnt that when overriding methods (and hiding fields) in sub classes, they can still be accessed from the super class by using the 'super' keyword.
What I want to know is, should the 'super' keyword be used for non-overridden methods?
Is there any difference (for non-overridden methods / non-hidden fields)?
I've put together an example below.
public class Vehicle {
private int tyreCost;
public Vehicle(int tyreCost) {
this.tyreCost = tyreCost;
}
public int getTyreCost() {
return tyreCost;
}
}
and
public class Car extends Vehicle {
private int wheelCount;
public Vehicle(int tyreCost, int wheelCount) {
super(tyreCost);
this.wheelCount = wheelCount;
}
public int getTotalTyreReplacementCost() {
return getTyreCost() * wheelCount;
}
}
Specifically, given that getTyreCost() hasn't been overridden, should getTotalTyreReplacementCost() use getTyreCost(), or super.getTyreCost() ?
I'm wondering whether super should be used in all instances where fields or methods of the superclass are accessed (to show in the code that you are accessing the superclass), or only in the overridden/hidden ones (so they stand out).
Don't use the super keyword to refer to other methods which aren't overridden. It makes it confusing for other developers trying to extend your classes.
Let's look at some code which does use the super keyword in this way. Here we have 2 classes: Dog and CleverDog:
/* file Dog.java */
public static class Dog extends Animal {
private String name;
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
/* file CleverDog.java */
public class CleverDog extends Dog {
public CleverDog(String name) {
super(name);
}
public void rollover() {
System.out.println(super.getName()+" rolls over!");
}
public void speak() {
System.out.println(super.getName() + " speaks!");
}
}
Now, imagine you are a new developer on the project, and you need some specific behavior for a clever dog who is on TV: that dog has to do all its tricks, but should go by its fictitious TV name. To accomplish this, you override the getName(...) method...
/* file DogOnTv.java */
public class DogOnTv extends CleverDog {
String fictionalName;
public DogOnTv(String realName, String fictionalName) {
super(realName);
fictionalName = fictionalName;
}
public String getName() {
return fictionalName;
}
}
... and fall into a trap set by the original developer and their unusual use of the super keyword!
The code above isn't going to work - because in the original CleverDog implementation, getName() is invoked using the super keyword. That means it always invokes Dog.getName() - irrelevant of any overriding. Consequently, when you use your new DogOnTv type...
System.out.println("Showcasing the Clever Dog!");
CleverDog showDog = new CleverDog("TugBoat");
showDog.rollover();
showDog.speak();
System.out.println("And now the Dog on TV!");
DogOnTv dogOnTv = new DogOnTv("Pal", "Lassie");
dogOnTv.rollover();
... you get the wrong output:
Showcasing the Clever Dog!
Tugboat rolls over!
Tugboat speaks!
And now the Dog on TV!
Pal rolls over!
Pal speaks!
This is not the usual expected behavior when you override a method, so you should avoid creating this kind of confusion using the super keyword where it doesn't belong.
If, however, this is actually the behavior you want, use the final keyword instead - to clearly indicate that the method can't be overridden:
/* file CleverDog.java */
public class CleverDog extends Dog {
public CleverDog(String name) {
super(name);
}
public final String getName() { // final so it can't be overridden
return super.getName();
}
public void rollover() {
System.out.println(this.getName()+" rolls over!"); // no `super` keyword
}
public void speak() {
System.out.println(this.getName() + " speaks!"); // no `super` keyword
}
}
You are doing the right way by not using the super keyword for accessing getTyreCost.
But you should set your members private and only use the getter method.
Using super keyword should be reserved for constructors and overridden methods which need to explicitly call the parent method.
This would be dependent on how you plan to use the code. If you specify super.getTyreCost() and then later override that method. You will still be calling the method on the superclass, not the overridden version.
In my opinion, calling super is likely to lead to more confusion later on, so is probably best specified only if you have an explicit need to do so. However, for the case you have presented here - there will be no difference in behavior.
It depends on your needs and your desires. Using super forces the compile/application to ignore any potential methods in your current class. If you want to communicate that you only want to use the parent's method, then using super is appropriate. It will also prevent future modifications to your class to accidentally override the parent method thereby ruining your expected logic.
However, these cases are fairly rare. Using super everywhere within your class will lead to very confusing & cluttered code. In most general cases, just calling the method within your own class and allowing the compiler/jvm to determine which method (super or local) needs to be called is more appropriate. It also allows you to override/modify/manipulate the super's returning values cleanly.
If you use super, you are explicitly telling to use super class method (irrespective of sub class has overridden method or not), otherwise first jvm checks for the method in subclass (overridden method if any), if not available uses super class method.
overriding means redefining a method from the superclass inside a subclass with identical method signature. In your case, the getTyreCost() method has not been overridden, you have not redefined the method in your subclass, so no need to use super.getTyreCost(), only getTyreCost() will do(just like super.getTyreCost() will do the same way). super keyword is used when a method has been overridden, and you want a method call from within your subclass to be implemented in the superclass.
Technically, the one that's invoked in this case is the inherited version, for which the implementation is actually provided by the parent class.
There can be scenarios where you must use the super keyword. e.g. if Car had overridden that method, to provide a different implementation of itself, but you needed to invoke the implementation provided by the parent class then you would have use the super keyword. In that case, you could not afford to omit the super keyword because if you did then you would be invoking the implementation provided by the child class itself.
It is advised that further changes to the inherited class will not necessitate addition of the super qualifier and also prevent errors if missed.

Why cannot we override static method in the derived class [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can we override static method in Java?
We cannot override the static methods of the base class.
Actually I tried something like this:
// Base class
public class StaticExampleImpl {
protected String name="overriding";
public static void display(){
System.out.println("static method display : base class");
}
}
Then the derived class is as follows:
//derived class
public class StaticDemo extends StaticExampleImpl {
// cannot override the static methods...
//#Override
public static void display(){
System.out.println("child!!! static method display");
}
public static void main(String[] args) {
StaticDemo d=new StaticDemo();
d.display(); // derived class display is called rather than Base class.
}
}
So, when I uncomment the #Override method, it gives error as "Static methods cannot be overriden". But with commenting it works fine. So, when we create the Objects and call the static methods with the instances, those work fine. so what is the difference??
because static methods are not get inherited.
When you uncomment #Override it means you are trying to override the
static method which is not possible thats why you are getting an
error.
But when you comment //#Override it means you are declaring a new
method in child class.
Static methods does not belong to an instance of a class, it belongs to the actual class.
When you call d.display();, you are really calling the static method of the StaticDemo d reference's static method.
if you did :
StaticExampleImpl d2 = new StaticDemo();d2.display(), you will find that it calls the base class's display.
However, don't do this. It leads to confusing code, and is a bad way to implement inheritance poorly.
Overriding depends the an instance of a class. polymorphismis that you can subclass a class and the objects implementing those subclasses will have different behaviors for those method defined in the superclass (and overridden in the subclasses) .static methods does not belong to an instance of a class so the concept is not applicable.
Static methods cannot be inherited. If you want to call the 'base' class static method, you have to explicitely call StaticExampleImpl.display().
Static methods are bound to class they can't be inherited thats why you can't have base class static method in derived class.
If you are trying to override a static method, there is probably something wrong with your design.
OOP and Polymorphism allows you to do the following:
public class MyClass1 {
public String toString() { return "MyClass1 Instance"; }
}
public class MyClass2 extends MyClass1 {
#Override
public String toString() { return "MyClass1 Instance"; }
}
public void printSomething(MyClass1 myclass1){
System.out.println(myclass1);
}
Inside printSomething, the toString method which is going to be called is the one on the runtime type of myClass1: when you pass inside printSomething an instance of MyClass2, its compile-type will be MyClass1 but its runtime type will be MyClass2
It is clear that to use polymorphism you need objects instances, where the actual runtime type could different from the compile type. Static methods however do not belong to any object instance, but to the class. Why don't you explain us what you are trying to achieve?
The following code:
StaticExampleImpl one = new StaticExampleImpl();
StaticDemo two = new StaticDemo();
StaticExampleImpl three = two;
one.display();
two.display();
three.display();
Will yield the following output:
static method display : base class
child!!! static method display
static method display : base class
As you can see, the method does not get inherited. This is why they are called 'static methods': they are called statically, not dynamically, as instance methods would be. The compile-time type of the class is what matters when calling static methods, not the runtime type.
This is also why you shouldn't call static methods through object instances. Always call them like this:
StaticExampleImpl.display();
StaticDemo.display();
This completely takes away the confusion that might (will) come up when people expect inheritance to work for these methods.
any static block in java, may be static variables, methods are loaded when the class is loaded. You probably know about class loader in java. So thing is static block (methods, variables or anything is static) is loaded once. So you can’t actually override any static block.
Commenting #Override means that you are writing another static method in sub class, but not just overriding base class method.

Confused with Java Overriding the access level [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why can't you reduce the visibility of a method in a java subclass?
How come I can override a private method in superclass with a public when in a subclass, but I cannot override a public method in the superclass into private method in subclass?
Why?
Thank you in advance.
Overriding a method can't ever reduce the visibility. Allowing that would violate the Liskov Substitution Principle, which states (simplified) that all objects of a derived class B must have the same properties as the base class A. In this case one such "property" would be a public method foo which would be "lost" if B had that same method, but made it protected.
Also, since private methods are not inherited (try calling it from a derived class!) they can't ever be overriden. You can have a public method with the same name as a private one in the base class, but that's not overriding, it's simply a new method with the same name, but not other relation. Calls to the private method in the base class will not call the public method in the superclass, even when executed on objects of the superclass!
In other words: private methods never use runtime polymorphism.
See this sample:
public static class Base {
public void callBoth() {
foo();
bar();
}
private void foo() {
System.out.println("Base.foo");
}
protected void bar() {
System.out.println("Base.bar");
}
}
public static class Sub extends Base {
public void foo() {
System.out.println("Sub.foo");
}
public void bar() {
System.out.println("Sub.bar");
}
}
When executing new Sub().callBoth() the output will be this:
Base.foo
Sub.bar
Because it doesn't break the class contract to make a method more available. If Kitten subclasses Animal, and Animal has a public method feed(), then Kitten must also have a public method feed(), as it must be possible to treat any instance of Kitten like an instance of Animal. Redefining the access level to private would break that.
If the public method became private, then it would not be possible to up cast the instance into its parent class (because one of the methods would be unavailable).
If the private method became public, then it would be possible to up case the instance into its parent class (because then you would just have no way to grab the private / publicly overriden method).
The access level can't be more restrictive than the overridden method.
private-->[default]-->protected-->public
By overriding you're saying that your subclass can be called with the same api but may function differently. Making something public increases the access level - so you're not removing guaranteed functionality.
By making a public method private (if you could actually do this) you'd be removing functionality, so breaking the "contract". It also doesn't make sense in that the method could still be called publicly, it's just that the public call would access the public method in the superclass, which would be counterintuitive.

Categories