I have a main method in my overall parent class, outside of that main method I have two other methods that I will call inside the main method. Each of these outside methods call a method that was defined in, not the child, but the grandchild class.
Here is where I get really confused. In my big parent class, the two methods that aren't the main method take in an array that is the type of the child class. This is because each item in the array is a different type the grandchild classes. I get that because the methods that I'm calling in the parent class aren't defined in the child class (they are defined in the grandchild class) that is why they cannot be called. Is there a way to typecast the indexes to each individual grandchild class type in a for loop in the array? Or any other way?
Sorry if this is a super confusing way to phrase this question.
The normal way to do this is for the parent class to be declared abstract, and to declare that the method should exist. The grandchild class will supply a version of the method. For example:
public abstract class Doubler {
int a;
public Doubler(int a) {
this.a = a;
}
abstract int modifyResult(int aResult);
int calculate() {
int rv = a * 2;
return modifyResult(rv);
}
}
public class DoublerAndAdder extends Doubler {
int b;
public DoublerAndAdder(int a, int b) {
super(a);
this.b = b;
}
#Override
public int modifyResult(int aResult) {
return aResult + b;
}
}
calculate() is allowed to call modifyResult() even though modifyResult() is declared abstract and there is no implementation. Calling DoublerAndAdder.calculate() will run Doubler.calculate(), which will call DoublerAndAdder.modifyResult().
If you can't make the parent class abstract, the parent class can provide a version of the method which doesn't do anything:
public abstract class Doubler {
int a;
public Doubler(int a) {
this.a = a;
}
public int modifyResult(int aResult) {
return aResult;
}
int calculate() {
int rv = a * 2;
return modifyResult(rv);
}
}
Related
class abstract Parent ()
{
private int a;
private final int b = a + 1; // a is null at that point
}
class Child extends Parent
{
public Child()
{
a = 2;
}
}
That wouldn't really be a problem in C++ (because pointers), but I'm not sure how to handle this issue in Java. Obviously a is equal to 0 when Parent tries to initiate b.
I initially tried calling super() after setting a, but apparently super() has to be called first in child's constructor. I don't want to set b in Childs and I'd prefer b to be final too. Any ideas?
What you want cannot be done like this, what you need to do is pass the value of a to a constructor of Parent:
abstract class Parent {
private int a;
private final int b;
protected Parent(int a) {
this.a = a;
b = a + 1;
}
}
And define Child as:
class Child extends Parent {
public Child() {
super(2);
}
}
This is a very basic question about subclasses in java, I still don't get it...
Suppose I have a superclass with three fields and with only the default constructor:
public class Superclass {
public int a;
public int b;
public int c;
}
and I want to add a field x. I cannot change Superclass, so I make a subclass:
public class Subclass extends Superclass {
public int x;
public Subclass(Superclass s) {
super();
// what to do??
}
}
I now want to generate a Subclass object from an existing Superclass object:
Superclass s = new Superclass();
s.a = "a";
s.b = "b";
Subclass sc = new Subclass(s);
sc.x = "x";
such that I can still access sc.a, sc.b etc.
How can I best do this without assigning all these fields 'by hand' in the constructor of the subclass?
You have to assign a value to the variables either in the base-class constructor or in the child class.
You can declare a parameterized constructor in sub-class to assign the value to a variable in the superclass
class Subclass extends Superclass {
public int x;
public Subclass(int a,int b, int c,int x) {
super();
this.x = x;
this.a=a;
this.b=b;
this.c=c;
}
}
Or you can declare a parameterized constructor in BaseClass, and in child class, instead of calling super(), call that parametrized constructorsuper(a,b,c)
class Superclass {
public int a;
public int b;
public int c;
public Superclass(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
class Subclass extends Superclass {
public int x;
public Subclass(int a,int b, int c,int x) {
super(a,b,c);
this.x = x;
}
}
Other than copying by hand you can't.
Java is not JavaScript where objects are prototypes of other objects, instead in Java, classes subclass other classes.
I now want to generate a Subclass object from an existing Superclass
object
In fact no, you will instantiate a Subclass object by relying on the state of a Superclass object.
As you pass the SuperClass as parameter of the Subclass constructor, you just need to use fields of it to invoke the super constructor if you declare it :
public Subclass(Superclass s) {
super(s.a, s.b, s.c); // constructor may simplify
}
Or if you have a super constructor with no arg :
public Subclass(Superclass s) {
a = s.a;
b = s.b;
c = s.c;
}
Note that in Java using the private modifier for instance fields is strongly encouraged and you should access to field via public methods.
A cleaner way for your constructor would look like :
public SuperClass(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
public Subclass(Superclass s) {
super(s.getA(), s.getB(), s.getC()); // constructor may simplify
}
If you truly cannot change the superclass, then the only way you can inspect and modify the values of the member variables is by using reflection.
You should note that if getters and setters aren't exposed to subclasses (i.e. they are private) then there's a question of whether the original creator of class wanted you to ever have access to the contained variables in the first place. Would your assignments change the behaviour of the parent in an unpredictable/unsupported way?
If the SuperClass is of your own design, then you should ensure that you always use getters and setters so that you may define the proper protocol (way to interact) with your class unambiguously. This rule also applies for the visibility of class constructors. Generally speaking, every member variable of a class should be possible to initialize via a class constructor; whether that constructor is visible, or exposes all of the possible parameters to subclasses or upon allocation by external sources, is a different story.
Why is the parent class method called when I am creating a child object. This is not even a static method.
class Parent {
public String pubMethod(Integer i) {
return "p";
}
}
public class Child extends Parent {
public String pubMethod(int i) {
return "c";
}
public static void main(String[] args) {
Parent u = new Child();
System.out.println(u.pubMethod(1)); // Prints "p" why??
}
}
Here I am passing a primitive int . Still it goes to the parent method.
Any explanation?
When you call u.pubMethod(1), the compiler considers only the signatures of the methods of Parent class, since Parent is the compile-type type of u. Since public String pubMethod(Integer i) is the only method of Parent having the required name, that's the selected method. public String pubMethod(int i) of Child class is not considered as a candidate, since Parent has no method of such signature.
In run-time, the method of the sub-class, public String pubMethod(int i), cannot override the super-class method public String pubMethod(Integer i), since it has a different signature. Therefore the Parent class method is executed.
In order for the Child class to be executed, you must either change its signature to match the Parent class method's signature, which will allow it to override the Parent class method:
public class Child extends Parent {
#Override
public String pubMethod(Integer i) {
return "c";
}
}
Or you can add a second method to the Parent class, which the existing Child class method will override:
class Parent {
public String pubMethod(Integer i) {
return "pInteger";
}
public String pubMethod(int i) {
return "pint";
}
}
In the first case, the compiler will still have a single method to choose - public String pubMethod(Integer i) - but in run-time the Child class method will override it.
In the second case, the compiler will have two methods to choose from. It will choose public String pubMethod(int i), since the type of the literal 1 is int. In run-time, the Child class public String pubMethod(int i) method will override it.
I think you didnt create your child object properly, you have:
Parent child = new Child();
But you should have:
Child child = new Child();
class Parent {
private int var = 1;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
class Child extends Parent {
private int var = 2;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
And now, when testing it, we get 2.
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.getVar());
I am casting the child object to a Parent explicitly and making my intentions clear
why then when i do parent.getVar() i get 2 ?
Child child = new Child();
Parent parent = (Parent)child;
You are simply using a super class reference to point. Your object is still of class Child and that will never change. So you would always get 2.
So when you call
System.out.println(parent.getVar());
at compile time it checks whether getVar() is present in class of reference Parent which is true. So it compiles. At runtime it knows the class of actual object which is Child and executes corresponding method.
Your object is Child here. But you are using Parent super class reference. At runtime, the object is of type Child, hence your code calling the child method results in getting 2.
The child getVar has overwritten the parent getVar method so even though your reference is typed as the parent, it's still the child and so still returns 2.
Having a known reference to the Child class you could have a special method on the child to access the parent var:
class Child extends Parent {
...
public int getParentVar() {
return super.getVar();
}
}
All methods in Java are virtual. That means that the reference type does not matter, what matters is the object type. You clearly have a reference to Child object, this is why Child's getVar() method is being executed.
What is even more fun to realize, that you have two different fields with name var, one in Parent and one in Child classes.
That's exactly the idea of OO: you can have different "childs" extending one parent with different implementations of methods (override) and in runtime the implementation that is called will be of the current object (polymorphism), regardless what you casted it to: during runtime the variables/class members will be read from the 'current' environment (the child in our case).
The use of such behavior (polymorphism) can be demonstrated with the following:
abstract class Shape {
abstract public double getArea();
}
class Square extends Shape {
double edge = 2.0;
public double getArea() {
return edge * edge;
}
}
class Circle extends Shape {
double radius = 2.0;
public double getArea() {
return Math.PI * radius * radius;
}
}
public class TestShapes {
public static void main(String[] args) {
Shape[] shapeArray = new Shape[2];
shapeArray[0] = new Square();
shapeArray[1] = new Circle();
for (Shape p: shapeArray) {
// every shape "knows" how to calculate its own area
// there's no need to find out which type of shape is it
// and there's no need to cast anything!
System.out.println("Area: " + p.getArea());
}
}
}
That said, if you want to call from the child to a parent-method (which is a bad practice!) you can do it using super keyword:
class Child extends Parent {
private int var = 2;
public int getVar() {
return super.getVar();
}
}
// usage:
Child c = new Child();
System.out.println(c.getVar()); // will print "1"
The private modifier specifies that the member can only be accessed in its own class. But am I able to access it using a public method that get inherited from base class. Can someone explain me why? Does this mean object of Child class contain a member called b?
Here's the code:
package a;
public class Base {
private int b;
public int getB() {
return b;
}
public void exposeB() {
System.out.println(getB());
}
public Base(int b) {
this.b = b;
}
}
package b;
public class Child extends Base {
Child(int b) {
super(b);
}
public static void main(String args[]) {
Child b = new Child(2);
// Prints 2
System.out.println("Accessing private base variable" + b.getB());
}
}
you are not accessing the private variable in your super class directly. you are implementing the concept of Encapsulation. you are using the public getter method(in this case getB()) to make your private data accesed by other classes. thus, you can access private variable b through public getter but you never cant access b directly on its instace from another/subclass
In class Base, the field b is private but getB() is public so anybody can call that method.
What you can expect to fail compilation is something like:
System.out.println( "Accessing private base variable" + b.b );
(unless that line is called from within a method of Base itself).
You will not be able to access b directly in Child because it is private. You can, however, use the base-class's getB method which is public (and hence can be called anywhere).
To allow only extending classes and other classes in your package to access the field, you can declare it as protected.
class A {
private int n;
public A(int n) { this.n = n; }
public int n() { return n; }
}
class B extends A {
public B(int n) { super(n); }
public void print() { System.out.println(n); } // oops! n is private
}
class A {
protected int n;
public A(int n) { this.n = n; }
public int n() { return n; }
}
class B extends A {
public B(int n) { super(n); }
public void print() { System.out.println(n); } // ok
}
The private modifier means that you can't reference that field outside the class. Because getB() is public, however, you can reference that method. The getB() method can reference the private b field, because it's inside the class, and therefore can access it.
Private variable means that you can't access directly the variable from its class.... Declaring that variable private means that you can't do this
Myclass.myprivatevariable = 3
This will throw a compile error complaining that myprivatevariable is not visible fro the outside
But, as you did.... Declaring an internal method as getter or setter, public, you are allowing the user, only just through that method, to access indirectly that variable... That is always the preferred way to do.