I'm misunderstanding something really basic with inheritance.
I have a parent class:
public class Parent {
String s = "Parent";
Parent () {}
String getS() {
return this.s;
}
}
and a child class:
public class Child extends Parent {
String s = "Child";
Child() { }
}
Main is like:
Parent parent = new Parent();
Child child = new Child();
Log.e(TAG, "parent:" + parent.getS());
Log.e(TAG, "child:" + child.getS());
I expect parent.getS() to return "Parent" and child.getS() to return "Child" but both return "Parent." Doesn't the method prefix determine the this for the method when called this way?
Thank you
Steve S.
Your getS() methods from parent class is inherited in Child class
and hence it is available for Child object.
Overriding is only for methods and not for instance variables.
So even if you define a new variable with same name, it will not take effect as it will not be overridden
You should create a getter method i.e. getS() in the Child class to retrieve "Child" when you call child.getS() in your main method. In this way, you override the getS() method that was inherited from the Parent class.
The way you would set the s-member in the parent-portion of a child-class, would be to offer a protected constructor (it could, of course, also be public):
protected Parent(String s) { this.s = s; }
which sets the string to the given value. You would then call this constructor as the first call in your child-constructor with
super("Whatever you want");
Related
This question is regarding Implementation Decision of super and this in Java. Consider,
Parent class contains a variable name and a method getName()
public class Parent {
protected String name = "Parent";
protected String getName(){
return this.name;
}
}
And Child class inherits Parent class but has its own name variable
public class Child extends Parent {
protected String name = "Child";
protected void printNames() {
System.out.println("Parent: " + super.getName());
System.out.println("Child: " + this.getName());
}
public static void main(String[] args) {
Child c = new Child();
c.printNames();
}
}
Output:
Parent: Parent
Child: Parent
From output, we can see that: When the method getName() is invoked from Child class with super context, it returns "Parent", but when invoked with this context, it again returns "Parent"
If the method is only present in Parent class, but the data members with same access modifier present in both,
Why shouldn't this.getName() from Child class return "Child" because it is-a Parent thus has getName() as its method
UPDATE
This question is not about how to get "Child" printed or overriding, its about implementation decision of this by Core Java Team, and its intended for them.
Fields are not overridable only methods are, the fields can only be hidden or not. this actually refers to the current Object which is of type Parent in the method Parent#getName() such that it will get the value of the variable name defined in Parent or potentially a parent class but not in a sub class like Child.
Here is a simple code snippet that shows the idea:
Child child = new Child();
// Show the variable name of the class Child
System.out.println(child.name);
// Show the variable name of the class Parent which is what this.name
// does in the getName method
System.out.println(((Parent)child).name);
Output:
Child
Parent
If u want to get 'child' as output you have to override the getname() method otherwise it is inherited,it will always show the 'parent' as output.
You need to add a getName() method to the child class. Right now, when you invoke this.getName(), the parent version is called since it is not overridden in the child class.
Just override the getName() method in your Child class
#Override
protected String getName() {
return name;
}
Update
If you don't want to override the getName() method, you can do like this :
set the name value in the Child constructor since it is a protected attribute
do not override the name attribute anymore in the Child class
public class Child extends Parent {
public Child() {
super();
this.name = "Child";
}
// ...
}
Let there are classes:
class Parent {
public Parent getParent() {
...
}
}
class Child extends Parent{
public Parent getChild() {
...
}
}
//instantiating Child by using reference of Parent
Parent parent = new Child();
when I use:
//Works fine
Parent parentObject = parent.getParent();
When I use:
//Doesn't works
Child childObject = parent.getChild();
But when type cast object:
//Works fine
Child childObejct = ((Child)parent).getChild();
being as programmer this is something hectic to type cast explicitly for every call where I wanted to use child members by reference of parent class.
You declared a variable of type Parent named parent that is actually a Child.
If you don't cast the variable you can use only the methods of class Parent.
If you cast the variable to the real type (that in this case is Child) you can access to all the methods of class Child and its super class Parent too.
Note: to have less misunderstandings it is better to name the variable child also if you assign it to the type Parent, so it is clear that this is a real Child.
It is not so complicated. When you have an up-cast, it is simple for the compiler to determine the real type and do the cast because you know every class is simply extended from one parent.
But when you are down-casting an object, compiler can not infer that an object with a Parent reference is which Child object in the runtime because every Parent class can have multiple Child class.
Good Luck.
You would do something like this? I did not understand what you want...
abstract class Parent {
public Parent(){
}
public abstract void doStuff();
}
class Child extends Parent{
public Child() {
super();
}
#Override
public void doStuff() {
// TODO Auto-generated method stub
}
In the main do this
Child c = new Child();
c.doStuff();
//Doesn't works
// parent.getChild() returning Parent object and you are trying to assign to child object, which is not possible implicitly.
Child childObject = parent.getChild();
You can try some more cases by changing as below too:
class Parent {
public Parent getParent() {
return new Parent();
}
}
class Child extends Parent{
public Child getChild() {
return new Child();
}
// to access methods of child class using Parent class,
//You should Override(same method Names and signatures) the methods of Parent Class
public Parent getParent() {
return new Parent();
}
}
Please help me to understand how inheritance works.
If I have two classes, parent and child. When I create an instance of child is parent class instance constructed as well or not?
My code of Parent class.
public class Parent {
private char s;
#Override
public int hashCode() {
return s;
}
}
And Child
public class Child extends Parent {
private int i;
public Child(int i) {
super();
this.i = i;
}
#Override
public int hashCode() {
return i;
}
}
And finally the test
public class Main {
public static void main(String[] args) {
Child child = new Child(100);
System.out.println(child.hashCode());
System.out.println(child.getClass().getSuperclass().hashCode());
}
}
In output I get
100
2000502626
So the hashes of objects are different. It means that when I create instance of Child it is also created instance of Parent. Am I right?
Your question has nothing to do with inheritance.
the 100 you get from child instance's hashcode() method, as you expected.
The 2000502626 was from Parent.class, not Parent object.
Parent.class has type java.lang.Class
parent object has type Parent
When you create a Child object a Parent constructor is invoked as well, because a Child is a Parent.
But when you do this:
System.out.println(child.getClass().getSuperclass().hashCode());
you're not invoking Parents instance hashode. You are invoking hashCode() of the instance of the Class object.
See what child.getClass().getSuperclass() returns. It returns an instance of type Class not of type Parent/Child.
You cannot invoke Parents instance methods using child.getClass().getSuperClass() - that doesn't return the instance of a type, but an object representing this type.
Try doing this in child method:
#Override
public int hashCode() {
System.out.println("In child hashCode: " + i);
System.out.println("Parents hashCode: " + super.hashCode());
return i;
}
This will return 100 and 0, as Parents s hasn't been initialized.
Actually, there will be just one child object created. Since every child is a parent, the parent constructor will be invoked. if you print this in both child as well as parent instance methods, it will print the same (child object)
check - this question
If I have two classes, parent and child, When I create an instance of child is parent class instance constructed as well or not?
Yes. It works through Constructor. When you call constructor of your child class to create object, it first calls its parent class contructor and hence creates object of parent class
Yes. Both parent and child object are created. The child class constructor calls the parent(super) class constructor first, then only other functions of the child class are performed. As you can see from your own code two different values getting printed.
public class Parent
{
Child child1;
public Parent()
{
child1.Name = "abc";
}
...
}
Gets a NullReferenceException. I thought the Parent() constructor calls the Child() constructor first, so that it is possible to access child1 object later in the Parent() constructor???
You need to create an instance of the child; either initialize it as you define it:
Child child1 = new Child();
Or in the Parent constructor:
public Parent(){
child1 = new Child();
child1.Name = "Andrew";
}
The parent class's constructor doesn't call constructors for its members. When the member is a reference, it's just set to null. You need to explicitly allocate it by calling child1 = new Child
Members are not implicitly constructed. They're initialized with their default values (i.e. null for reference type members), which is why your child1 member is null.
You need to create an instance of child1:
public Parent
{
child1 = new Child();
}
On a sidenote, I think you are being confused by constructor call rules for inherited classes. If your Child class inherited your Parent class, the Parent class' default (i.e. parameterless) constructor would be implicitly called (if it existed):
class Parent
{
protected string member;
public Parent()
{
member = "foo";
}
}
class Child : Parent
{
public Child()
{
// member is foo here; Parent() is implicitly called
}
}
In a Java program, I have multiple subclasses inheriting from a parent (which is abstract). I wanted to express that every child should have a member that is set once only (which I was planning to do from the constructor). My plan was to code s.th. like this:
public abstract class Parent {
protected final String birthmark;
}
public class Child extends Parent {
public Child(String s) {
this.birthmark = s;
}
}
However, this seems to not please the Java gods. In the parent class, I get the message that birthmark "might not have been initialized", in the child class I get "The final field birthmark cannot be accessed".
So what's the Java way for this? What am I missing?
You can't do it because while comparing the parent class, the compiler can't be sure that the subclass will initialize it. You'll have to initialize it in the parent's constructor, and have the child call the parent's constructor:
public abstract class Parent {
protected final String birthmark;
protected Parent(String s) {
birthmark = s;
}
}
public class Child extends Parent {
public Child(String s) {
super(s);
...
}
}
Pass it to the parent constructor:
public abstract class Parent {
private final String birthmark;
public Parent(String s) {
birthmark = s;
}
}
public class Child extends Parent {
public Child(String s) {
super(s);
}
}
Another Java-ish way to do this is probably to have the parent class to define an abstract "getter", and have the children implement it. It's not a great way to do it in this case, but it in some cases it can be exactly what you want.
I would do it like this:
public abstract class Parent
{
protected final String birthmark;
protected Parent(final String mark)
{
// only if this makes sense.
if(mark == null)
{
throw new IllegalArgumentException("mark cannot be null");
}
birthmark = mark;
}
}
public class Child
extends Parent
{
public Child(final String s)
{
super(s);
}
}
final means that the variable can be initialized once per instance. The compiler isn't able to make sure that every subclass will provide the assignment to birthmark so it forces the assignment to happen in the constructor of the parent class.
I added the checking for null just to show that you also get the benefit of being able to check the arguments in one place rather than each cosntructor.
Why not delegate initialization to a method. Then override the method in the parent class.
public class Parent {
public final Object x = getValueOfX();
public Object getValueOfX() {
return y;
}
}
public class Child {
#Override
public Object getValueOfX() {
// whatever ...
}
}
This should allow custom initialization.
Yes, the final members are to be assigned in the class in which they are declared. You need to add a constructor with a String argument to Parent.
Declare a constructor in the superclass that's called by the subclass.
You must set the field in the superclass to make sure it's initialized, or the compiler can't be sure the field is initialized.
You probably want to have a Parent(String birthmark) constructor so that you can ensure in your Parent class that final is always initialized. Then you can call super(birthmark) from your Child() constructor.