I know there have been lots of thread about Java inheritance (and i already read it), but they all stand for "how it is", and I need knowledge "how to change it". So, we have 2 classes:
class t1{
public int a=5;
public void get(){
System.out.println(a);
}
}
class t2 extends t1{
public int a = 1;
}
and now :
t2 z = new t2();
z.get();
And we get 5
Of cource it is just example, but what i want to do is make some common methods in superclass which will use field from inherited class, ex. user messages
Is there any way to do this? If not then why i would use superclasses, can i use anything else?
Thanks in advance
You should use a constructor and possibly a getter
class t1{
public final int a;
public t1() {
this(5);
}
protected t1(int a) {
this.a = a;
}
public void get(){
System.out.println(a);
}
}
class t2 extends t1{
public t2() {
super(1);
}
}
now
t2 z = new t2();
z.get();
prints 1
Yes, there is a way do to this. You can apply pattern which called "Template method". Here is an example
class Base {
void someMethod() {
int value = getValue();
// calculate something
}
protected abstract int getValue();
}
class Derived extends Base {
int getValue() {
return 5;
}
}
Where getValue() is your template method and you can insert any logic in your inherited classes implementations.
you are shadowing/hiding the variable of t1!
t1 can see the variable of t2 and prints it's own a-value in the get method.
you don't need to declare a again because the a of t1 can be seen everywhere
if you want another default value for a in object of type t2 override the default constructor.
public t2() {
this.a = 1;
}
Polymorphism works only for methods, not for fields and you cant change this Java mechanism. It means that late binding will find correct body of method depending on class of object
class X{
void sayHello(){
System.out.println("Hello from X");
}
}
class Y extends X{
void sayHello(){
System.out.println("Hello from X");
}
}
//...
X obj = new Y();
obj.sayHello();// even if you are using X reference body of method will
// come from Y class
But fields are not polymorphic so if method uses some field it will use this field all the time (once again, late binding will not search for newest field declared in class of current object). That is why you are seeing 5 as result.
If you want to simulate" polymorphic behaviour of field used in methods body your best choice is to let derived class set new value of that field in base class like in Peter Lawrey's answer (big +1 for him).
Related
I'm new to java. Recently I saw some code which was similiar to this:
class A {
protected int myInt;
public static void main(String[] args) {
B b = new B();
b.myFunction();
}
}
class B extends A {
public void myFunction() {
this.myInt = 10;
}
}
As far as I know, when creating a subclass instance, an instance of its parent is created as well. All protected and public members of base class are accessible from the subclass.
If I override myInt there will be a difference between this.myInt to super.myInt because each class will have its own myInt (B will have access to both).
So, my question is: if I don't override myInt, which form is preferable, this.myInt or super.myInt?
You only need to use this or super when need to specify which scope are you using/referring to. In your case, I'll prefer to omit the this to simplify the readability.
super is used to represents the current instante of a parent class while this is used to represents the current class. You only need to used this or super if some variable or method overlaps (Have the same name) with one in a wide scope.
eg. If you have define a method parameter with the same name as class attribute, you need to use this to indicate that you are using the class attribute and not the method parameter.
public class A {
public int myInt = 1;
public static void main(String[] args) {
B b = new B();
b.myFunction(3);
}
}
class B extends A {
public int myInt = 2;
public void myFunction(int myInt){
System.out.println(myInt); // The parameter
System.out.println(this.myInt); // myInt from the current class (B)
System.out.println(super.myInt); // myInt from the parent class (A)
}
}
This example will print:
3
2
1
If you don't have this kind of collission, the use of this is optional:
public void myFunction2(){
System.out.println(myInt); // Both refers to the same
System.out.println(this.myInt); // variable myInt from class B
}
It's a matter of taste and the project's standards/guidelines more than anything else.
Personally, I wouldn't use either, and would just write myInt = 10.
Only one instance is created. If you instantiate a derived object, the parents constructor is called, but only one object is created. Also, the term this is more so used when there are different variables with the same name being referenced in a class.
For example a simple constructor:
class SupClass{
public int a = 1;
int incA(){
return ++a;
}
}
class MyClass extends SupClass {
public int a = 10;
public int b = 20;
MyClass() {};
MyClass(int a, int b){
this.a = a;
this.b = b;
}
int incA(){
return ++a;
}
public static void main(String args[])
{
SupClass d = new MyClass();
System.out.println(d.a); //1, members known of type SupClass at compile-time,
System.out.println(d.incA()); //11, methods are virtual, decided at run-time
}
}
Only use the super method when you want to explicitly use the value that is in the super class. To answer your question, only methods can be overwritten, member variables can not.
class A
{
int a = 2, b = 3;
public void display()
{
int c = a + b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Why does the output come out as 5,5? And not 5,11?.How would the y.display() method work?
why does the output comes 5,5?
Because A.display() only knows about the fields A.a and A.b. Those are the only fields that any code in A knows about. It looks like you expect the declarations in B to "override" the existing field declarations. They don't. They declare new fields which hide the existing fields. Variables don't behave virtually in the way that methods do - the concept of overriding a variable simply doesn't exist. From the JLS section 8.3:
If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class.
You can get the effect you want by changing B so that its constructor changes the values of the existing fields that it inherits from A instead:
class B extends A {
B() {
a = 5;
b = 6;
}
}
Note that these are not variable declarations. They're just assignments. Of course in most code (well, most code I've seen anyway) the fields in A would be private, so couldn't be accessed from B, but this is just example for the purpose of explaining the language behaviour.
In class A you declare fields a and b. The method display uses these fields. In class B you declare NEW fields of the same name. You're actually hiding the old fields not "overriding" them. To assign different values to the same fields use a constructor:
class A {
A(int a, int b) {
this.a = a;
this.b = b;
}
A() {
this(2, 3);
}
int a,b;
public void display() {
int c=a+b;
System.out.println(c);
}
}
class B extends A {
B() {
super(5, 6);
}
}
When doing this:
class B extends A
{
int a = 5, b = 6;
}
you are not redefining a and b, you're creating new variables with the same names. So you end up with four variables( A.a, A.b, B.a, B.b).
When you call display() and calculate the value of c, A.a and A.b will be used, not B.a and B.b
There isn's anything called variable overriding. That is why you are getting the same result in both the cases.
The reason is that Java uses the concept of lexical scope for variable resolution.
Fundamentally, there are two possible options to resolve free variables in a function ('free' means not local and not bound to function parameters):
1) against the environment in which the function is declared
2) against the environment in which the function is executed (called)
Java goes the first way, so free variables in methods are resolved [statically, during compilation] against their lexical scope (environment), which includes:
method parameters and local method variables
field declarations in the class containing method declaration
public field declarations in parent class
and so on, up the chain of inheritance
You would see this behaviour implemented in most programming languages, because it is transparent to developer and helps prevent errors with shadowing of variables.
This is opposite to the way methods work in Java:
class A {
public void foo() {
boo();
}
public void boo() {
System.out.println("A");
}
}
class B extends A {
#Override
public void boo() {
System.out.println("B");
}
}
class Main {
public static void main(String[] args) {
B b = new B();
b.foo(); // outputs "B"
}
}
This is called dynamic dispatch: method call is resolved dynamically in runtime against the actual object, on which it is called.
When you compile your code it pretty much becomes like:
class A extends java.lang.Object
{
int a=2,b=3;
public void display()
{
int c=a+b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
public void display()
{
super(); //When you call y.display() then this statement executes.
}
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
And hence, when super calls, the method of class A is being called.
Now go to method of class A. Here int c = a + b; means
c = this.a + this.b; which is 2 + 3.
And the result is 5.
Class B declares variables in B scope, public void display() is part of A class and knows only about its own scope variables.
It's the inheritance functaionality which gives the output 5,5.
Java doesn't have anything like variable overriding. Thus, when the method display() is invoked, it accesses the variables inside the parent class 'A' and not the variables inside the subclass 'B'.
It can be explained with the same reason of why you can't print a variable declared in a subclass (and not in superclass) inside superclass method. The superclass method simply doesn't have access to the subclass variables.
However, you'll be able to print 5,11 if you have accessor methods to the fields in both the classes and you use those accessor methods to get the values instead of directly accessing using variable names. (even if the display() method is present only in superclass). This is because the overridden accessor methods are invoked (in second case) which return the values from the subclass.
Why does the output come out as 5,5? And not 5,11?
Whenever we have same instance variables (applicable to class variable as well) in a class hierarchy, the nearest declaration of the variable get the precedence. And in this case, nearest declaration of a and b from display () method is A’s. So class B’s instance variables go hidden. Hence in both cases, 5 gets printed.
How would the y.display() method work?
Another alternative is to have getter in both classes to get value of a and b.
class A
{
int a = 2, b = 3;
public int getA() {
return a;
}
public int getB() {
return b;
}
public void display()
{
int c = getA() + getB();
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
public int getA() {
return a;
}
public int getB() {
return b;
}
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Prints
5
11
I'd like to better understand what is the difference in referring to a class field by using this.field and field alone as in
this.integerField = 5;
and
integerField = 5;
this keyword refers to the current object.
usually we use this.memberVariable to diffrentiate between the member and local variables
private int x=10;
public void m1(int x) {
sysout(this.x)//would print 10 member variable
sysout(x); //would print 5; local variable
}
public static void main(String..args) {
new classInst().m1(5);
}
Off from the concrete question,
the use of this In Overloaded constructors:
we can use this to call overloaded constructor like below:
public class ABC {
public ABC() {
this("example");to call overloadedconstructor
sysout("no args cons");
}
public ABC(String x){
sysout("one argscons")
}
}
The use of this keywords lets you disambiguate between member variables and locals, such as function parameters:
public MyClass(int integerField) {
this.integerField = integerField;
}
The code snippet above assigns the value of local variable integerField to the member variable of the class with the same name.
Some shops adopt coding standards requiring all member accesses to be qualified with this. This is valid, but unnecessary; in cases where no collision exists, removing this does not change the semantic of your program.
When you are in an instance method, you may need to specify to which scope you refer a variable from. For example :
private int x;
public void method(int x) {
System.out.println("Method x : " + x);
System.out.println("Instance x : " + this.x);
}
While, in this example, you have two x variables, one is a local method variable and one is a class variable. You may distinguish between the two with this to specify it.
Some people always use this before using a class variable. While it is not necessary, it may improve code readability.
As for polymorphism, you may refer to the parent class as super. For example :
class A {
public int getValue() { return 1; }
}
class B extends A {
// override A.getValue()
public int getValue() { return 2; }
// return 1 from A.getValue()
// have we not used super, the method would have returned the same as this.getValue()
public int getParentValue() { return super.getValue(); }
}
Both keywords this and super depend on the scope from where you are using it; it depends on the instance (object) you are working with at run-time.
It's exactly the same. Because you often type this.xyz it's a shortcut that means the same thing if there is a field by that name and there isn't a local variable that shadows it.
Though they look and act the same, there is a difference when the same name is shared between a field and a method argument, e.g.:
private String name;
public void setName(String name){
this.name = name;
}
name is the passed parameter, and this.name is the proper class field.
Notice that typing this.... prompts you a list of all the class fields [and methods] in many IDEs.
From the Java tutorials:
Within an instance method or a constructor, this is a reference to the
current object — the object whose method or constructor is being
called. You can refer to any member of the current object from within
an instance method or a constructor by using this.
So, when you call a method within a object the call looks like this:
public class MyClass{
private int field;
public MyClass(){
this(10); // Will call the constructor with a int argument
}
public MyClass(int value){
}
//And within a object, the methods look like this
public void myMethod(MyClass this){ //A reference of a object of MyClass
this.field = 10; // The current object field
}
}
Why can't I cast a base class instance to a derived class?
For example, if I have a class B which extends a class C, why can't I do this?
B b=(B)(new C());
or this?
C c=new C();
B b=(B)c;
Alright let me be more specific as to what I'm trying to do. Here's what I have:
public class Base(){
protected BaseNode n;
public void foo(BaseNode x){
n.foo(x);
}
}
public class BaseNode(){
public void foo(BaseNode x){...}
}
Now I want to create a new set of classes which extend Base and Basenode, like this:
public class Derived extends Base(){
public void bar(DerivedNode x){
n.bar(x);//problem is here - n doesn't have bar
}
}
public class DerivedNode extends BaseNode(){
public void bar(BaseNode){
...
}
}
So essentially I want to add new functionality to Base and BaseNode by extending them both, and adding a function to both of them. Furthermore, Base and BaseNode should be able to be used on their own.
I'd really like to do this without generics if possible.
Alright so I ended up figuring it out, partly thanks to Maruice Perry's answer.
In my constructor for Base, n is instantiated as a BaseNode. All I had to do was re-instantiate n as a DerivedNode in my derived class in the constructor, and it works perfectly.
because if B extends C, it means B is a C and not C is a B.
rethink what you are trying to do.
The existing answers are fine in terms of an abstract argument, but I'd like to make a more concrete one. Suppose you could do that. Then this code would have to compile and run:
// Hypothetical code
Object object = new Object();
InputStream stream = (InputStream) object; // No exception allowed?
int firstByte = stream.read();
Where exactly would the implementation of the read method come from? It's abstract in InputStream. Where would it get the data from? It simply isn't appropriate to treat a bare java.lang.Object as an InputStream. It's much better for the cast to throw an exception.
In my experience it's tricky to get "parallel class hierarchies" like the one you're describing to work. You may find that generics help, but it can get hairy very quickly.
You need to use the instanceof keyword to check the type of object referenced by n and typecast the object and call the bar() method. Checkout Derived.bar() method bellow
public class Test{
public static void main(String[] args){
DerivedNode dn = new DerivedNode();
Derived d = new Derived(dn);
d.bar( dn );
}
}
class Base{
protected BaseNode n;
public Base(BaseNode _n){
this.n = _n;
}
public void foo(BaseNode x){
n.foo(x);
}
}
class BaseNode{
public void foo(BaseNode x){
System.out.println( "BaseNode foo" );
}
}
class Derived extends Base{
public Derived(BaseNode n){
super(n);
}
public void bar(DerivedNode x){
if( n instanceof DerivedNode ){
// Type cast to DerivedNode to access bar
((DerivedNode)n).bar(x);
}
else {
// Throw exception or what ever
throw new RuntimeException("Invalid Object Type");
}
}
}
class DerivedNode extends BaseNode{
public void bar(BaseNode b){
System.out.println( "DerivedNode bar" );
}
}
You can create a constructor for B that takes C as a parameter.
See this post for ideas to do what you're trying to do.
Base classes shouldn't know anything about classes derived from them, otherwise the problems highlighted above will arise. Downcasting is a 'code smell', and downcasting in the base class to a derived class is particularly 'smelly'. Such designs can lead to difficult to resolve circular dependencies too.
If you want a base class to make use of derived class implementations use the Template method pattern i.e add a virtual or abstract method in your base class and override and implement it in the derived class. You can then safely call this from the base class.
You can't do that because C does not necessarily implement the behaviours you created when you extended it in B.
So, say C has a method foo(). Then you know that you can call foo() on a B, as B extends C, so you can cast accordingly a treat a B as if it was a C with (C)(new B()).
However - if B has a method bar(), nothing in the subclass relationship says that you can call bar() on C too. Thus you cannot treat a C as if it were a B, and so you cannot cast.
In your exemple, you can cast n into a DerivedNode if you are certain that n is an instance of DerivedNode, or you can use generics:
public class Base<N extends BaseNode> {
protected N n;
public void foo(BaseNode x){
n.foo(x);
}
}
public class BaseNode {
public void foo(BaseNode x){...}
}
public class Derived extends Base<DerivedNode> {
public void bar(DerivedNode x){
n.bar(x); // no problem here - n DOES have bar
}
}
public class DerivedNode extends BaseNode {
public void bar(BaseNode){
...
}
}
Because if B extends C, then B might have stuff that isn't in C (like instance variables you initialize in the constructor that are not in new C())
Why are we not able to override an instance variable of a super class in a subclass?
He perhaps meant to try and override the value used to initialize the variable.
For example,
Instead of this (which is illegal)
public abstract class A {
String help = "**no help defined -- somebody should change that***";
// ...
}
// ...
public class B extends A {
// ILLEGAL
#Override
String help = "some fancy help message for B";
// ...
}
One should do
public abstract class A {
public String getHelp() {
return "**no help defined -- somebody should change that***";
}
// ...
}
// ...
public class B extends A {
#Override
public String getHelp() {
return "some fancy help message for B";
// ...
}
Because if you changed the implementation of a data member it would quite possibly break the superclass (imagine changing a superclass's data member from a float to a String).
Because you can only override behavior and not structure. Structure is set in stone once an object has been created and memory has been allocated for it. Of course this is usually true in statically typed languages.
Variables aren't accessed polymorphically. What would you want to do with this that you can't do with a protected variable? (Not that I encourage using non-private mutable variables at all, personally.)
class Dad{
public String name = "Dad";
}
class Son extends Dad{
public String name = "Son";
public String getName(){
return this.name;
}
}
From main() method if you call
new Son().getName();
will return "Son"
This is how you can override the variable of super class.
Do you mean with overriding you want to change the datatype for example?
What do you do with this expression
public class A {
protected int mIndex;
public void counter(){
mIndex++;
}
}
public class B extends A {
protected String mIndex; // Or what you mean with overloading
}
How do you want to change the mIndex++ expression without operator overloading or something like this.
If you have the need to override an instance variable, you are almost certainly inheriting from the worng class.
In some languages you can hide the instance variable by supplying a new one:
class A has variable V1 of type X;
class B inherits from A, but reintroduces V1 of type Y.
The methods of class A can still access the original V1. The methods of class B can access the new V1. And if they want to access the original, they can cast themself to class A (As you see dirty programming provokes more dirty progrtamming).
The best solution is to find another name for the variable.
you can override a method,that is all right
but what do you mean by overriding a variable?
if you want to use a variable at any other place rather than super class
u can use super.
as in
super(variable names);
why do you want to override a variable?
i mean is there any need?
we can not overriding structure of instance variables ,but we ovverride their behavior:-
class A
{
int x = 5;
}
class B extends A
{
int x = 7:
}
class Main
{
public static void main(String dh[])
{
A obj = new B();
System.out.println(obj.x);
}
}
in this case output is 5.