I have a class with many subclasses,but when passing a subclass instance to some method which is supposed to receive an instance of the superclass, the attribute of the subclass is overwritten.
For example, the following code prints 0. What should I do to it so that it prints the subclass parameter value?
class A{
int cost;
}
class B extends A{
int cost = 10;
}
class Test{
public static void main(String[] args){
B b = new B();
method4A(b);
}
static void method4A(A a){
System.out.println(a.cost);
}
}
While fields can be shared within inheritance, given the right access modifiers (i.e. anything not private pretty much - default access will not work across different packages though), they are resolved at compile time, contrary to methods which are resolved at runtime (the latter is called virtual method invocation).
ints default to 0, and you're passing an A reference type, so A.cost's value of 0 is printed.
You have a range of options here:
Do not declare cost in B and assign cost value from A in B's constructor, or instance initializer, etc. to 10
An ugly, explicit cast in method4A, e.g. System.out.println(((B)a).cost);
Passing a B reference type instead of A in method4A
Keep both cost variables and declare a simple getter in A returning cost, and #Override it in B with the same implementation (it'll return B's cost even when invoked on a A reference if the instance actually is B)
Your problem doesn't have any relation with the overriding.
Declaring twice the same field in both classes (class and subclass) may be error-prone.
Do you really need to define two distinct fields ?
Why not reuse the field of the parent class in the subclass or provide a access to ?
Of course, in some specific cases, it is acceptable and desirable to define two distinct fields but for these cases generally you use the private modifier to isolate them.
A natural way to define such as behavior is providing a private field for cost and getter and setter in the parent class.
In this way, the subclass has way to value/set this field.
It could for example value the field from its constructor :
class A{
private int cost;
public void setCost(int cost){
this.cost = cost;
}
public int getCost(){
return cost;
}
}
class B extends A{
public B(){
this.setCost(10);
}
}
class Test{
public static void main(String[] args){
B b = new B();
method4A(b);
}
static void method4A(A a){
System.out.println(a.getCost());
}
}
You can use method overriding with getters like this:
class A {
int cost;
public int getCost() {
return cost;
}
}
class B extends A {
int cost = 10;
public int getCost() {
return cost;
}
}
class Test {
public static void main(String[] args) {
B b = new B();
method4A(b);
}
static void method4A(A a) {
System.out.println(a.getCost());
}
}
Related
I was asked the following question:
Assuming all instance fields and all instance methods of class A in Java are private, which of the following are correct:
A is immutable
A is not for sure immutable because it could be that it extends a not-immutable class
A is not for sure immutable because you might be able to change its fields from static methods
I thought the correct answer was 1 but turns out 2 and 3 are both correct and 1 is not.
How come if everything is private you can still modify the fields?
Why if it extends a not immutable class, but still have everything private, it might be now immutable?
What does it mean to change its fields from static methods?
A could extend a class with fields that are public, in which case, those fields can be modified despite A itself not defining any mutable fields, as it will inherit fields and instance methods from its parent class.
Consider the following code:
class Child extends Parent {
private String name;
}
class Parent {
public int id;
}
class TestChild {
public static void main(final String[] args) {
final Child child = new Child();
//String s = child.name;<--The field Child.name is not visible
System.out.println("Previous id: " + child.id);
child.id = 100;//<--We can modify this because it is defined as public in Parent
System.out.println("Updated id: " + child.id);
}
}
The output will be:
Previous id: 0
Updated id: 100
For the next case, it seems that the question meant methods as in instance methods, not specifying whether or not there are static methods. Static methods that are public can be called anywhere and create side effects by modifying static fields and can also access private instance fields on instances of A, which makes A not immutable.
Point 2:
class B {
public int bValue;
}
class A extends B {
private int aValue;
}
An instance of A is not immutable because it has inherited a bValue field that can be changed.
Point 3:
class A {
private int x;
public static void mutate(A a) {
a.x += 1;
}
}
Instances of A can be mutated by calling the static method A.mutate, which has full access to A's private fields. The stipulation as it now reads, "all instance methods of class A in Java are private", does not apply to static methods.
All the previous answers were right. On the question regarding
A is not for sure immutable because you might be able to change its fields from static methods
can be achieved like
public class Test {
public static void main(String[] args) {
A a = new A(10);
System.out.println(a);
A.mutateObj(20);
System.out.println(a);
}
}
class A {
private static A a;
private int x;
A(int x) {
this.a = this;
this.x = x;
}
public static void mutateObj(int b) {
a.x = b;
}
#Override
public String toString() {
return "A{" +
"x=" + x +
'}';
}
}
Result =>
A{x=10}
A{x=20}
I have a super class named TestSuper
public class TestSuper {
int a = 0;
}
and I have 2 sub classes named TestSub and TestSub2 that extend TestSuper
public class TestSub extends TestSuper{
int a=1;
}
public class TestSub2 extends TestSuper{
int a=2;
}
in my main class i created a method that takes in a type TestSuper and returns the a value of it and in the main i display it on the console
public class Main {
public static void main(String[] args){
System.out.println(test(new TestSub())+" "+test(new TestSub2()));
}
public static int test(TestSuper b){
return b.a;
}
}
but the output is "0 0" instead of "1 2", what do I do?
You need to cast the reference so say which one you want.
public static int test(TestSuper b){
return b instanceof TestSub ? ((TestSub) b).a :
b instanceof TestSub2 ? ((TestSub2) b).a :
b.a;
}
If this seems needlessly complicated, it is. You should use polymorphism instead.
public class TestSuper {
int a = 0;
public int getA() { return a; }
}
public class TestSub extends TestSuper {
int a = 1;
public int getA() { return a; }
}
public class TestSub2 extends TestSuper {
int a = 2;
public int getA() { return a; }
}
public static int test(TestSuper b) {
return b.getA();
}
First understand the difference between hiding and overriding: https://docs.oracle.com/javase/tutorial/java/IandI/override.html
Then create a getter method in the base-class which you can override in the subclass.
You can look into the theory behind this, and then do the only reasonable thing -forget about writing such kind of code.
In good OOP you consider your fields to be part of your "secret" internal implementation. You don't use fields of sub classes in the super class context. Period.
You are even very conservative about making a field protected in the superclass and to use that in subclasses.
When you call test method like this:
test(new TestSub())+" "+test(new TestSub2())
You use upcasting. Upcasting seperates interface and implementation for an object. But for seperating interface and implementation and achieving true implementation in polymorphism, you must use polymorphic structures. The instance variables aren't polymorphic. Because of this, actually you call a variable which is in TestSuper class.
Only instance methods are polymorphic.
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
}
}