Java Inheritance: Why super class variable is referred - java

I have a super class "Sam" and a sub-class "SubSam"
public class Sam {
String msg;
String msg1;
Sam(String mm, String mm1) {
msg = mm;
msg1 = mm1;
}
#Override
public String toString() {
return this.msg + " " + this.msg1;
}
}
class SubSam extends Sam {
String msg1="C";
public static void main(String[] args) throws Exception {
SubSam obj = new SubSam();
System.out.println(obj);
}
SubSam() {
super("A", "B");
}
}
The output is:
A B
Why "toString()" is referring the instance fields of "Sam" instead of "SubSam". The output should be: A C
I am thinking over it for a long time now, but not getting?

Because instance variables in Java aren't overridden, quite simply. A subclass can define a variable with the same name as one defined in one of its superclasses, but it counts as a separate variable for all intents and purposes.
For example, consider the following code:
public class A {
public String var;
}
public class B extends A {
public int var;
}
Given those definitions, instances of B will have two variables, one being of type String, the other of type int, but both will be named var. They are still separate variables which can be independently assigned to and read from, and Java does not consider there being anything wrong with this.
If you want to override behavior as you indicate you want, you need to use methods instead. For instance, you could do it like this:
public class A {
public String msg;
private String msg1;
public A(String mm, String mm1) {
this.msg = mm;
this.msg1 = mm1;
}
public String msg1() {
return(this.msg1);
}
#Override
public String toString() {
return(this.msg + " " + msg1());
}
}
public class B extends A {
public B() {
super("A", "B");
}
#Override
public String msg1() {
return("C");
}
}
Now, if you call System.out.println(new B());, it will print A C.

You're not overriding toString, so the toString method of the superclass is called. It prints msg and msg1 for the superclass, not for the subclass.

You are setting the msg1 in the sub-class, but in it's contructor you are passing
super("A","B");
At this point the variable that are being initialized in the super i.e. the contructor of main class are the main class' variable that are being used using the this keyword in toString method.

Related

Use constructor overload from within class constructor [duplicate]

Is it possible to call a constructor from another (within the same class, not from a subclass)? If yes how? And what could be the best way to call another constructor (if there are several ways to do it)?
Yes, it is possible:
public class Foo {
private int x;
public Foo() {
this(1);
}
public Foo(int x) {
this.x = x;
}
}
To chain to a particular superclass constructor instead of one in the same class, use super instead of this. Note that you can only chain to one constructor, and it has to be the first statement in your constructor body.
See also this related question, which is about C# but where the same principles apply.
Using this(args). The preferred pattern is to work from the smallest constructor to the largest.
public class Cons {
public Cons() {
// A no arguments constructor that sends default values to the largest
this(madeUpArg1Value,madeUpArg2Value,madeUpArg3Value);
}
public Cons(int arg1, int arg2) {
// An example of a partial constructor that uses the passed in arguments
// and sends a hidden default value to the largest
this(arg1,arg2, madeUpArg3Value);
}
// Largest constructor that does the work
public Cons(int arg1, int arg2, int arg3) {
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
}
}
You can also use a more recently advocated approach of valueOf or just "of":
public class Cons {
public static Cons newCons(int arg1,...) {
// This function is commonly called valueOf, like Integer.valueOf(..)
// More recently called "of", like EnumSet.of(..)
Cons c = new Cons(...);
c.setArg1(....);
return c;
}
}
To call a super class, use super(someValue). The call to super must be the first call in the constructor or you will get a compiler error.
[Note: I just want to add one aspect, which I did not see in the other answers: how to overcome limitations of the requirement that this() has to be on the first line).]
In Java another constructor of the same class can be called from a constructor via this(). Note however that this has to be on the first line.
public class MyClass {
public MyClass(double argument1, double argument2) {
this(argument1, argument2, 0.0);
}
public MyClass(double argument1, double argument2, double argument3) {
this.argument1 = argument1;
this.argument2 = argument2;
this.argument3 = argument3;
}
}
That this has to appear on the first line looks like a big limitation, but you can construct the arguments of other constructors via static methods. For example:
public class MyClass {
public MyClass(double argument1, double argument2) {
this(argument1, argument2, getDefaultArg3(argument1, argument2));
}
public MyClass(double argument1, double argument2, double argument3) {
this.argument1 = argument1;
this.argument2 = argument2;
this.argument3 = argument3;
}
private static double getDefaultArg3(double argument1, double argument2) {
double argument3 = 0;
// Calculate argument3 here if you like.
return argument3;
}
}
When I need to call another constructor from inside the code (not on the first line), I usually use a helper method like this:
class MyClass {
int field;
MyClass() {
init(0);
}
MyClass(int value) {
if (value<0) {
init(0);
}
else {
init(value);
}
}
void init(int x) {
field = x;
}
}
But most often I try to do it the other way around by calling the more complex constructors from the simpler ones on the first line, to the extent possible. For the above example
class MyClass {
int field;
MyClass(int value) {
if (value<0)
field = 0;
else
field = value;
}
MyClass() {
this(0);
}
}
Within a constructor, you can use the this keyword to invoke another constructor in the same class. Doing so is called an explicit constructor invocation.
Here's another Rectangle class, with a different implementation from the one in the Objects section.
public class Rectangle {
private int x, y;
private int width, height;
public Rectangle() {
this(1, 1);
}
public Rectangle(int width, int height) {
this( 0,0,width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
This class contains a set of constructors. Each constructor initializes some or all of the rectangle's member variables.
As everybody already have said, you use this(…), which is called an explicit constructor invocation.
However, keep in mind that within such an explicit constructor invocation statement you may not refer to
any instance variables or
any instance methods or
any inner classes declared in this class or any superclass, or
this or
super.
As stated in JLS (§8.8.7.1).
Yes, any number of constructors can be present in a class and they can be called by another constructor using this() [Please do not confuse this() constructor call with this keyword]. this() or this(args) should be the first line in the constructor.
Example:
Class Test {
Test() {
this(10); // calls the constructor with integer args, Test(int a)
}
Test(int a) {
this(10.5); // call the constructor with double arg, Test(double a)
}
Test(double a) {
System.out.println("I am a double arg constructor");
}
}
This is known as constructor overloading.
Please note that for constructor, only overloading concept is applicable and not inheritance or overriding.
Using this keyword we can call one constructor in another constructor within same class.
Example :-
public class Example {
private String name;
public Example() {
this("Mahesh");
}
public Example(String name) {
this.name = name;
}
}
Yes it is possible to call one constructor from another. But there is a rule to it. If a call is made from one constructor to another, then
that new constructor call must be the first statement in the current constructor
public class Product {
private int productId;
private String productName;
private double productPrice;
private String category;
public Product(int id, String name) {
this(id,name,1.0);
}
public Product(int id, String name, double price) {
this(id,name,price,"DEFAULT");
}
public Product(int id,String name,double price, String category){
this.productId=id;
this.productName=name;
this.productPrice=price;
this.category=category;
}
}
So, something like below will not work.
public Product(int id, String name, double price) {
System.out.println("Calling constructor with price");
this(id,name,price,"DEFAULT");
}
Also, in the case of inheritance, when sub-class's object is created, the super class constructor is first called.
public class SuperClass {
public SuperClass() {
System.out.println("Inside super class constructor");
}
}
public class SubClass extends SuperClass {
public SubClass () {
//Even if we do not add, Java adds the call to super class's constructor like
// super();
System.out.println("Inside sub class constructor");
}
}
Thus, in this case also another constructor call is first declared before any other statements.
I will tell you an easy way
There are two types of constructors:
Default constructor
Parameterized constructor
I will explain in one Example
class ConstructorDemo
{
ConstructorDemo()//Default Constructor
{
System.out.println("D.constructor ");
}
ConstructorDemo(int k)//Parameterized constructor
{
this();//-------------(1)
System.out.println("P.Constructor ="+k);
}
public static void main(String[] args)
{
//this(); error because "must be first statement in constructor
new ConstructorDemo();//-------(2)
ConstructorDemo g=new ConstructorDemo(3);---(3)
}
}
In the above example I showed 3 types of calling
this() call to this must be first statement in constructor
This is Name less Object. this automatically calls the default constructor.
3.This calls the Parameterized constructor.
Note:
this must be the first statement in the constructor.
You can a constructor from another constructor of same class by using "this" keyword.
Example -
class This1
{
This1()
{
this("Hello");
System.out.println("Default constructor..");
}
This1(int a)
{
this();
System.out.println("int as arg constructor..");
}
This1(String s)
{
System.out.println("string as arg constructor..");
}
public static void main(String args[])
{
new This1(100);
}
}
Output -
string as arg constructor..
Default constructor..
int as arg constructor..
Calling constructor from another constructor
class MyConstructorDemo extends ConstructorDemo
{
MyConstructorDemo()
{
this("calling another constructor");
}
MyConstructorDemo(String arg)
{
System.out.print("This is passed String by another constructor :"+arg);
}
}
Also you can call parent constructor by using super() call
There are design patterns that cover the need for complex construction - if it can't be done succinctly, create a factory method or a factory class.
With the latest java and the addition of lambdas, it is easy to create a constructor which can accept any initialization code you desire.
class LambdaInitedClass {
public LamdaInitedClass(Consumer<LambdaInitedClass> init) {
init.accept(this);
}
}
Call it with...
new LambdaInitedClass(l -> { // init l any way you want });
Pretty simple
public class SomeClass{
private int number;
private String someString;
public SomeClass(){
number = 0;
someString = new String();
}
public SomeClass(int number){
this(); //set the class to 0
this.setNumber(number);
}
public SomeClass(int number, String someString){
this(number); //call public SomeClass( int number )
this.setString(someString);
}
public void setNumber(int number){
this.number = number;
}
public void setString(String someString){
this.someString = someString;
}
//.... add some accessors
}
now here is some small extra credit:
public SomeOtherClass extends SomeClass {
public SomeOtherClass(int number, String someString){
super(number, someString); //calls public SomeClass(int number, String someString)
}
//.... Some other code.
}
Hope this helps.
Yes it is possible to call one constructor from another with use of this()
class Example{
private int a = 1;
Example(){
this(5); //here another constructor called based on constructor argument
System.out.println("number a is "+a);
}
Example(int b){
System.out.println("number b is "+b);
}
You can call another constructor via the this(...) keyword (when you need to call a constructor from the same class) or the super(...) keyword
(when you need to call a constructor from a superclass).
However, such a call must be the first statement of your constructor. To overcome this limitation, use this answer.
The keyword this can be used to call a constructor from a constructor, when writing several constructor for a class, there are times when you'd like to call one constructor from another to avoid duplicate code.
Bellow is a link that I explain other topic about constructor and getters() and setters() and I used a class with two constructors. I hope the explanations and examples help you.
Setter methods or constructors
I know there are so many examples of this question but what I found I am putting here to share my Idea. there are two ways to chain constructor. In Same class you can use this keyword. in Inheritance, you need to use super keyword.
import java.util.*;
import java.lang.*;
class Test
{
public static void main(String args[])
{
Dog d = new Dog(); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.
Dog cs = new Dog("Bite"); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.
// You need to Explicitly tell the java compiler to use Argument constructor so you need to use "super" key word
System.out.println("------------------------------");
Cat c = new Cat();
Cat caty = new Cat("10");
System.out.println("------------------------------");
// Self s = new Self();
Self ss = new Self("self");
}
}
class Animal
{
String i;
public Animal()
{
i = "10";
System.out.println("Animal Constructor :" +i);
}
public Animal(String h)
{
i = "20";
System.out.println("Animal Constructor Habit :"+ i);
}
}
class Dog extends Animal
{
public Dog()
{
System.out.println("Dog Constructor");
}
public Dog(String h)
{
System.out.println("Dog Constructor with habit");
}
}
class Cat extends Animal
{
public Cat()
{
System.out.println("Cat Constructor");
}
public Cat(String i)
{
super(i); // Calling Super Class Paremetrize Constructor.
System.out.println("Cat Constructor with habit");
}
}
class Self
{
public Self()
{
System.out.println("Self Constructor");
}
public Self(String h)
{
this(); // Explicitly calling 0 args constructor.
System.out.println("Slef Constructor with value");
}
}
It is called Telescoping Constructor anti-pattern or constructor chaining. Yes, you can definitely do. I see many examples above and I want to add by saying that if you know that you need only two or three constructor, it might be ok. But if you need more, please try to use different design pattern like Builder pattern. As for example:
public Omar(){};
public Omar(a){};
public Omar(a,b){};
public Omar(a,b,c){};
public Omar(a,b,c,d){};
...
You may need more. Builder pattern would be a great solution in this case. Here is an article, it might be helpful
https://medium.com/#modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e
Yes, you can call constructors from another constructor. For example:
public class Animal {
private int animalType;
public Animal() {
this(1); //here this(1) internally make call to Animal(1);
}
public Animal(int animalType) {
this.animalType = animalType;
}
}
you can also read in details from
Constructor Chaining in Java
Originally from an anser by Mirko Klemm, slightly modified to address the question:
Just for completeness: There is also the Instance initialization block that gets executed always and before any other constructor is called. It consists simply of a block of statements "{ ... }" somewhere in the body of your class definition. You can even have more than one. You can't call them, but they're like "shared constructor" code if you want to reuse some code across constructors, similar to calling methods.
So in your case
{
System.out.println("this is shared constructor code executed before the constructor");
field1 = 3;
}
There is also a "static" version of this to initialize static members: "static { ... }"
I prefer this way:
class User {
private long id;
private String username;
private int imageRes;
public User() {
init(defaultID,defaultUsername,defaultRes);
}
public User(String username) {
init(defaultID,username, defaultRes());
}
public User(String username, int imageRes) {
init(defaultID,username, imageRes);
}
public User(long id, String username, int imageRes) {
init(id,username, imageRes);
}
private void init(long id, String username, int imageRes) {
this.id=id;
this.username = username;
this.imageRes = imageRes;
}
}

Why to use bounded type parameters in generic, if it is accepting child class object by default?

I am using bounded type parameters in generic (JAVA).
class First<T extends Use>{
T s;
First(T s){
this.s=s;
}
void setS(T s){
this.s=s;
}
void getS(){
System.out.println(s);
}
}
class UseChild extends Use{
public String toString(){
return "I am UseChild";
}
}
class Use{
public String toString(){
return "I am Use";
}
public static void main(String[] args){
First <Use> f1 = new First <Use> (new Use());
f1.getS();
f1.setS(new UseChild());
f1.getS();
}
}
Output is:
I am Use
I am UseChild
Till now its ok. I thought I can pass child class object to setS(), because "T extends Use" is there in Type-parameter, otherwise I could not.
But Output is same if I am using type-parameter without extends keyword as:
class First<T>
{
//Same code as above
}
My doubt is:
What is special about extends keyword if I can pass child class object to setS() without extends keyword?
Let's say Use defines a new method (instead of overriding toString):
class Use {
...
public void printMe() { // Some nonsensical method for demonstration
System.out.println("printing Use");
}
}
This bound would allow you to call this method from the First class:
class First<T extends Use> {
T s;
...
public void getS() {
s.printMe(); // not possible without the bound.
}
}
The way you're using First, you don't need generics at all. Using the type Use instead of T would work the same:
class First {
Use s;
First(Use s) {
this.s = s;
}
void setS(Use s) {
this.s = s;
}
void getS() {
System.out.println(s);
}
}
The output would be the same.
The <T extends Use> here acts as a restriction. It specifies that you can ONLY pass objects of type Use or that extend type Use.
Changing to <T> is equivalent to <T extends Object> - in other words, you will be able to pass any object.
The difference is that with First<T> you could pass any object, for example a LinkedList or a JFrame. With First<T extends Use> you can only pass objects of type Use or that extend type Use.
One way this can be very useful is if type Use has certain methods that you want your class First to use. In that case you will need to specify <T extends Use> so that First will be aware of the methods and properties of the Use class.
The Type-parameter(T) of any generic class accepts type-argument and children of type argument. We can pass object of UseChild in setS(), even if object of class First is created using Use as type-argument. Because UseChild is child class of Use. So following statements are perfectly valid together:
First<Use>f = new First<Use>(new Use());
f.setS(newUseChild());
Difference between bounded and unbounded types are not as it stated in the question. Actual difference between is discuss below:
If we do not use bounded type, then T extends Object, and s becomes reference variable of object type.
class Use
{
public String toString()
{
return "I am Use";
}
public void call()
{
System.out.println("I am call of Use");
}
public static void main(String[] args)
{
First <Use> f1 = new First <Use> (new Use());
f1.getS();
}
}
Lets check various fields of class First:
import java.lang.reflect.*;
class First<T>
{
T s;
First(T s)
{
this.s=s;
}
void setS(T s)
{
this.s=s;
}
void getS()
{
Field[] flds = this.getClass().getDeclaredFields();
for(Field f:flds)
{
String name = f.getName();
String type = f.getType().getName();
int i = f.getModifiers();
String modifier = Modifier.toString(i);
System.out.println("Name = "+name+" type= "+type);
}
System.out.println(s.getClass().getName());
}
}
Output is:
Name = s type= java.lang.Object
Use
So T extends java.lang.Object. s is reference variable of type java.lang.Object. We cannot call Use specific methods using variable s.
Lets check various fields of class First With bounded type:
import java.lang.reflect.*;
class First<T extends Use>
{
T s;
First(T s)
{
this.s=s;
}
void setS(T s)
{
this.s=s;
}
void getS()
{
Field[] flds = this.getClass().getDeclaredFields();
for(Field f:flds)
{
String name = f.getName();
String type = f.getType().getName();
int i = f.getModifiers();
String modifier = Modifier.toString(i);
System.out.println("Name = "+name+" type= "+type);
}
System.out.println(s.getClass().getName());
}
}
Output is:
Name = s type= Use
Use
So now T extends Use, instead of java.lang.Object. s is reference variable of type Use. As said by #jorn vernee now we can call Use specific methods from First.

how does base class know about sub class method?

public class BaseClass {
private String className;
public BaseClass() {
className = "[BaseClass]";
}
public void executeAB() {
System.out.println(className + " executingAB()");
executeA();
executeB();
}
public void executeA() {
System.out.println(this.className + " executingA()");
}
public void executeB() {
System.out.println(this.className + " executingB()");
}
}
public class SubClass extends BaseClass {
private String className;
public SubClass() {
this.className = "[SubClass]";
}
public void executeA() {
System.out.println(className + " executingA()");
}
public void executeC() {
System.out.println(className + " executingC()");
}
public static void main(String[] args) {
BaseClass t = new SubClass();
t.executeAB();
// t.executeC();
}
}
In above case , Calling t.executeAB() results in output:
[BaseClass] executingAB()
[SubClass] executingA()
[BaseClass] executingB()
My Question is:
How does BaseClass know about excuteA() method from SubClass, while at the same time t.executeC() call is not possible because BaseClass is not aware of executeC().
You have a misunderstanding of what you should be doing in inheritance. extends is a reserved word that was wisely chosen. The point of B extending A is to say that B is a subset of A with additional attributes. You're not supposed to redefine x in B; A should be handling x. You should have not className declared in both classes.
As for your example:
BaseClass t = new SubClass();
Calls the constructor for SubClass, which sets className of SubClass to [SubClass]. The super contructor is also called, and className in BaseClass is set to [BaseClass].
t.executeAB();
Prints the className for BaseClass which is [BaseClass] and then calls:
executeA();
executeB();
executeA() is a called from SubClass, since t is a SubClass and it's defined, so we get [SubClass] and finally, executeB() is called from BaseClass so again, we get [BaseClass]. As for why you can't call:
t.executeC()
Despite using the constructor for SubClass, t is a BaseClass. According to the principles of OOP, it makes sense that you can't call t.executeC(), since it is not defined for BaseClass.
You're defining your variable as BaseClass t = new SubClass(); which means you allow space for a different subclass to instantiate. However, in order for this to be possible without breaking existing code, you can only use methods that are defined in the baseclass.

Java field hiding for attributes

I just started to learn Java, so please bear with me if the answer is somewhat obvious. I did some research but no avail.
From what I understand, attributes are not overriden but only field hidden. To determine whether the attribute in the superclass or the subclass is used, Java will check the type of the reference.
Then I don't under stand the output here:
public class Super {
String str = "I'm super!\n";
public String toString() {
return str;
}
}
public class Sub extends Super {
String str = "I'm sub.\n";
}
public class TestFH {
public static void main(String[] args) {
Sub s1 = new Sub();
System.out.printf(s1.toString());
}
}
It gives me:
I'm super!
I understand that I can achieve what I want easily via method overriding. I'm just curious about what's happenning under the hood.
Thanks in advance.
When you call, s1.toString(), it's finding toString() method defined only in Super class hence using that method as super class methods are available in the sub class. Your super class method toString() is using it's own class variable str (with value initialized in super class) as the return value from the method and hence the behavior i.e. output as I'm super!.
If you want to get the output as I'm sub.\n then you need to reuse the same variable as in the super class and assign the new string value i.e. I'm sub.\n to it. Best option is to use constructors as:
public class Super {
String str = "I'm super!\n";
public Super(String stringValue){
this.str = stringValue;
}
public String toString() {
return str;
}
}
public class Sub extends Super {
public Sub(){
super("I'm sub.\n");
}
}
public class TestFH {
public static void main(String[] args) {
Sub s1 = new Sub();
System.out.printf(s1.toString());
}
}
You're hiding (shadowing) str in your child class. Since you have not overridden toString() in your child class, the call is being made in the parent class, and it sees the parent's str.
If you did this:
public class Sub extends Super {
public Sub() {
this.str = "I'm sub.\n";
}
}
It would output what you're expecting.
This call is using the super class:
Sub s1 = new Sub();
System.out.printf(s1.toString());
The reason is that Sub is not overriding str, it is just declaring another variable that happens to have the same name. In other words, sub is just hiding the variable in Super (data members are not polymorphic).
You could give them different names if they mean different things. Or maybe have the Sub access (or modify) the parent's attribute using a getter method.
you're not assigning the string literal, "I'm sub.\n" to the shared superclass field, you're creating a field local to the subclass and assigning it to that instead.
for example,
public class EncapsulationDemo {
public static void main(String[] args){
MySuperObject obj = new MySubObject();
System.out.println(obj); // prints I'm sub.
}
private static class MySuperObject{
String str = "I'm super."; // protected, can be accessed directly
// by subclasses
#Override
public String toString(){
return str;
}
}
private static class MySubObject extends MySuperObject{
MySubObject(){
super();
str = "I'm sub."; // assign to superclass field
}
}
}
for more information, please see Controlling Access to Members of a Class.

What's the difference between this and super keywords in java?

Check my coolMethod, babes:
package zoo;
public class Zoo {
public String coolMethod() {
return "Wow baby!";
}
}
My Moo Class, that extends my Zoo class, full of ways to do the same thing, which is calling my coolMethod.
package zoo;
public class Moo extends Zoo {
public void useAZoo(){
Zoo z = new Zoo();
System.out.println("A Zoo says: "+ z.coolMethod());
}
public void useMyCoolMethod(){
System.out.println("My cool method says: " + super.coolMethod());
}
public void useMyCoolMethodAgain(){
System.out.println("My cool method says: " + this.coolMethod()+ " (again)");
}
public void inheritMyMethod(){
System.out.println("My inhertied method says: " + coolMethod());
}
}
And my main, that calls my Moo class functionalities.
package javacert1;
import zoo.Moo;
public class Main {
public static void main(String[] args) {
Moo moo = new Moo();
moo.useAZoo();
moo.useMyCoolMethod();
moo.useMyCoolMethodAgain();
moo.inheritMyMethod();
}
}
As you can see, all those four calls get the same results. I'm learning Java and I practiced with an example that used the "this" but I had seen the use of "super" elsewhere so I tested it and the results where the same. Why is this? What's the major difference between a this and super keyword?
Since you have only one coolMethod, it is called in each case, regardless of qualifiers. However, if you override your method in Moo e.g. like this
public class Moo extends Zoo {
public String coolMethod() {
return "Yeah dude!";
}
// the rest is the same as above...
}
you will notice the difference between the calls to coolMethod() and this.coolMethod() versus the call to super.coolMethod().
this can be pointing to current object
super can be used for accessing Super class metods & variables
this() can be used to invoke a constructor of the same class
super() can be used to invoke a super class constructor
Difference with examples
Cool example, overmann :)
Here is another example ... has 2 source files - LevelSub.java which extends LevelSup.java
Save the 2 in some folder, compile using "javac LevelSub.java" (compiler will know from "extends" that it has to compile "LevelSup.java", too), and run "java LevelSub". The comments in the source code should tell you the difference.
this and super are used when there is a name clash for variables or methods (e.g., same name is used in super/sub classes or in a method body, or you want to call a method from the superclass that has been overridden). "this" refers to the current object instance and "super" refers to the one it is inheriting from. For no name clashes, the this or super prefix are redundant.
public class LevelSub extends LevelSup {
protected String myName;
public LevelSub (String myName) {
super ("SuperClass");
this.myName = myName; // sets up instance variable
}
public void print () {
System.out.println ("Hi, this is " + myName); // refers to this.myName
System.out.println ("I am inherited from " + super.myName);
System.out.println ("also known as " + defaultName); // gets from superclass
super.print(); // overridden method of superclass
}
public static void main (String[] args) {
new LevelSub("SubClass").print();
}}
and the other source ...
public class LevelSup {
// cannot be private if accessed by subclass
protected String myName, defaultName = "TopLevel";
public LevelSup (String name) {
myName = name; // this not required, no name clash
}
// cannot be private if accessed by subclass
public void print () {
System.out.println ("Hi, this is " + myName);
}
}
You are not overriding the coolMethod and you are inheriting it.
As a result it calls the same method.
Override coolMethod and see what happens.
super will call the method of base.
this will call method in this object
"this" refers to the object you're in. "super" refers to the parent of this object. I think you're missing the difference because of some other things you have going on.
For example, this code
public class Zoo {
public String coolMethod() {
return "Wow baby!";
}
}
public class Moo extends Zoo {
public void useAZoo(){
Zoo z = new Zoo();
System.out.println("A Zoo says: "+ z.coolMethod());
}
public void useMyCoolMethod(){
System.out.println("My cool method says: " + super.coolMethod());
}
public void useMyCoolMethodAgain(){
System.out.println("My cool method says: " + this.coolMethod()+ " (again)");
}
public void inheritMyMethod(){
System.out.println("My inhertied method says: " + coolMethod());
}
}
The method "coolMethod" is defined in Zoo, but it's a public method so it is naturally inherited by Moo. So, when you're within your Moo class and you call this.coolMethod or super.coolMethod, you end up with exactly the same thing. Where things get far more interesting is if you override the coolMethod in your subclass, like this:
public class Zoo {
public String coolMethod() {
return "Wow baby!";
}
}
public class Moo extends Zoo {
#Override
public String coolMethod() {
return "Moo baby!";
}
public void doIt() {
System.out.println("Using super: " + super.coolMethod());
System.out.println("Using this: " + this.coolMethod());
}
}
Try executing "doIt" in that case and I think you'll see the difference much easier.
In this case, they will do nothing different.
However, if you were to override coolMethod in the Moo class, the call to the super version will call the version in the Zoo class, but all the other versions will call the new overridden one.
To see the difference, overwrite the coolMethod in your subclass Moo:
public String coolMethod() {
return "Moo baby!";
}
I suggest you, to create a coolMethod in your Moo class, that print something different, from the one in the Zoo class

Categories

Resources