class Parent {
String st = "external";
void print() {
System.out.println(st);
System.out.println(this.st);
}
}
class Child extends Parent {
String st = "inner";
}
public static void main(String[] args) {
new Child().print(); // shows "external"
}
Why does print() called on subclass not show the string "inner"?
why print() called on subclass doesn't show string - "inner" ?
Because member variables cannot be overridden. The member variable st in class Child does not override the member variable st in class Parent. The two member variables are two separate variables, which happen to have the same name.
The methods in class Parent see the member variable st that is defined in class Parent, and not the one in class Child, even if the object is really an instance of class Child.
Only methods can be overridden.
More information in Oracle's Java Tutorials: Hiding Fields (thanks #JonK).
As the others mentioned the field st of the Parent class is hidden. Just an addition if you want it to print "inner".
Change Child class to this:
class Child extends Parent {
public Child() {
st = "inner";
}
}
This way the value of st from the Parent class is overriden!
why print() called on subclass doesn't show string - "inner" ?
why should it? you are calling the method print() that is only override in the parent class up there in the parent class st is only holding the value "external"
The other answers cover why the behavior you notice is expected, so I won't touch on that. In terms of a solution to your problem, there are a few worth mention (neglecting things like reflection and subclass casting; technically solutions, but poor ones).
Option 1: Set Parameter
As Will mentioned, can simply set the parameter in Child:
class Child extends Parent{
public Child() {
st = "inner";
}
}
Option 2: Method Override
Can also override the print() method (because, as mentioned, only methods can be overridden). Child would become something along the lines of:
class Child extends Parent{
...
#Override
void print() {
// Child-specific implementation here.
}
}
This will result in Child objects using their print method in place of Parent's method.
Option 3: Strategy Pattern
Another option is to use Strategy pattern. Consider the following:
public interface Strategy {
String getString();
}
public class ParentStrategy implements Strategy {
#Override
public String getString() {
return "external";
}
}
public class ChildStrategy implements Strategy {
#Override
public String getString() {
return "inner";
}
}
From here, all you need to do is change your Parent object so that it defaults to ParentStrategy, provide accessors to change the Strategy, change its print method to use the getString() method of its Strategy object, and change the Strategy in Child to use ChildStrategy:
class Parent{
Strategy strat = new ParentStrategy();
void setStrategy(Strategy s) {
strat = s;
}
void print() {
System.out.println(strat.getString());
}
}
class Child extends Parent{
public Child() {
super();
setStrategy(new ChildStrategy());
}
}
In real world applications, this pattern is a fundamental tool to making flexible applications.
Related
I have the following classes
class Person {
private String name;
void getName(){...}}
class Student extends Person{
String class;
void getClass(){...}
}
class Teacher extends Person{
String experience;
void getExperience(){...}
}
This is just a simplified version of my actual schema. Initially I don't know the type of person that needs to be created, so the function that handles the creation of these objects takes the general Person object as a parameter.
void calculate(Person p){...}
Now I want to access the methods of the child classes using this parent class object. I also need to access parent class methods from time to time so I CANNOT MAKE IT ABSTRACT.
I guess I simplified too much in the above example, so here goes , this is the actual structure.
class Question {
// private attributes
:
private QuestionOption option;
// getters and setters for private attributes
:
public QuestionOption getOption(){...}
}
class QuestionOption{
....
}
class ChoiceQuestionOption extends QuestionOption{
private boolean allowMultiple;
public boolean getMultiple(){...}
}
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption().getMultiple())
{...}
}
}
The if statement says "cannot find getMultiple for QuestionOption." OuestionOption has many more child classes that have different types of methods that are not common among the children (getMultiple is not common among the children)
NOTE: Though this is possible, it is not at all recommended as it kind of destroys the reason for inheritance. The best way would be to restructure your application design so that there are NO parent to child dependencies. A parent should not ever need to know its children or their capabilities.
However.. you should be able to do it like:
void calculate(Person p) {
((Student)p).method();
}
a safe way would be:
void calculate(Person p) {
if(p instanceof Student) ((Student)p).method();
}
A parent class should not have knowledge of child classes. You can implement a method calculate() and override it in every subclass:
class Person {
String name;
void getName(){...}
void calculate();
}
and then
class Student extends Person{
String class;
void getClass(){...}
#Override
void calculate() {
// do something with a Student
}
}
and
class Teacher extends Person{
String experience;
void getExperience(){...}
#Override
void calculate() {
// do something with a Teacher
}
}
By the way. Your statement about abstract classes is confusing. You can call methods defined in an abstract class, but of course only of instances of subclasses.
In your example you can make Person abstract and the use getName() on instanced of Student and Teacher.
Many of the answers here are suggesting implementing variant types using "Classical Object-Oriented Decomposition". That is, anything which might be needed on one of the variants has to be declared at the base of the hierarchy. I submit that this is a type-safe, but often very bad, approach. You either end up exposing all internal properties of all the different variants (most of which are "invalid" for each particular variant) or you end up cluttering the API of the hierarchy with tons of procedural methods (which means you have to recompile every time a new procedure is dreamed up).
I hesitate to do this, but here is a shameless plug for a blog post I wrote that outlines about 8 ways to do variant types in Java. They all suck, because Java sucks at variant types. So far the only JVM language that gets it right is Scala.
http://jazzjuice.blogspot.com/2010/10/6-things-i-hate-about-java-or-scala-is.html
The Scala creators actually wrote a paper about three of the eight ways. If I can track it down, I'll update this answer with a link.
UPDATE: found it here.
Why don't you just write an empty method in Person and override it in the children classes? And call it, when it needs to be:
void caluculate(Person p){
p.dotheCalculate();
}
This would mean you have to have the same method in both children classes, but i don't see why this would be a problem at all.
I had the same situation and I found a way around with a bit of engineering as follows - -
You have to have your method in parent class without any parameter and use - -
Class<? extends Person> cl = this.getClass(); // inside parent class
Now, with 'cl' you can access all child class fields with their name and initialized values by using - -
cl.getDeclaredFields(); cl.getField("myfield"); // and many more
In this situation your 'this' pointer will reference your child class object if you are calling parent method through your child class object.
Another thing you might need to use is Object obj = cl.newInstance();
Let me know if still you got stucked somewhere.
class Car extends Vehicle {
protected int numberOfSeats = 1;
public int getNumberOfSeats() {
return this.numberOfSeats;
}
public void printNumberOfSeats() {
// return this.numberOfSeats;
System.out.println(numberOfSeats);
}
}
//Parent class
class Vehicle {
protected String licensePlate = null;
public void setLicensePlate(String license) {
this.licensePlate = license;
System.out.println(licensePlate);
}
public static void main(String []args) {
Vehicle c = new Vehicle();
c.setLicensePlate("LASKF12341");
//Used downcasting to call the child method from the parent class.
//Downcasting = It’s the casting from a superclass to a subclass.
Vehicle d = new Car();
((Car) d).printNumberOfSeats();
}
}
One possible solution can be
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption() instanceof ChoiceQuestionOption)
{
ChoiceQuestionOption choiceQuestion = (ChoiceQuestionOption)q.getOption();
boolean result = choiceQuestion.getMultiple();
//do something with result......
}
}
}
I want to instantiate a child class in Java from within a parent class. However, when I do this, and attempt to call a parent's method from the constructor of the child (with super), the returned field is null. If I changed this to instantiating the parent from the main() method, the field returns how it is expected (a String). I'm not sure whats happening here, can anyone explain?
Main class:
public class MainFunc {
public static void main(String[] args) {
javaClass jv = new javaClass("Bobby");
jv.makeJ2();
}
}
Parent Class:
public class javaClass {
String name;
public javaClass(){
}
public javaClass(String s) {
setName(s);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void makeJ2 (){
javaClass2 jv2 = new javaClass2();
}
}
Child Class:
public class javaClass2 extends javaClass {
String name;
public javaClass2() {
super();
String superTitle = super.getName();
System.out.println("HEY " + superTitle);
}
}
This returns:
HEY null
Instead of:
HEY Bobby
You cannot access child class from parent class,child class has inherited the parent class, not the other way. But you can make your String static for it to work the way you want.
public class javaClass {
static String name;
Design wise, a parent should never instantiate a child class. It is not like human reproduction system. In OOPS world, child classes need to declare their own parents, and only these child classes know about their parents and not vice-versa.
Even though intention in the posted question is to make use of Inheritance, it is not happening by the virtue of the convoluted code. This is how the code is running:
Test creates a javaClass object named jv. At this point jv has an attribute name, value of which is set to Bobby
jv's makeJ2 method is called, this creates a very new object of the class javaClass2, named jv2. The parent class of this very new object does NOT have any field set, and nothing has been passed to the parent class's constructor. Hence there is NO relation between the parent of this new object jv2 and the previously created jv object and that is why:
String superTitle = super.getName(); returns null as expected
The exact problem is that the child object is not passing along any information for the parent's attributes to be set. That can happen through overloaded supers or by setting super properties but not just by calling super(). See a good explanation of how inheritance works in java.
Please do not use static just to make it work
Lastly, I suggest reading about composition too, as that is slightly more preferable over inheritance, for some good reasons.
In your child class you did not overload the constructor for name field. From the overloaded constructor you should invoke super(name);
The output that is generated is because of two reasons.
Because you have called super() in the javaClass2 constructor and not super(String str)
And because the parent java class that the child class is instantiating is not the same as the one you are calling the method makeJ2(jv.makeJ2()) from.
Also the blow link can help you understand the instance variable overriding in java.
Java inheritance overriding instance variable [duplicate]
Base on your progress:
You initiate the parent class:
javaClass jv = new javaClass("Bobby");
javaClass name attribute will be "Bobby"
Now the time you call:
jv.makeJ2();
It will initiate the new javaClass2:
javaClass2 jv2 = new javaClass2();
It call the super(); mean: javaClass() in javaClass not javaClass(String s)
So now your new child javaClass2 is extended from new javaClass wiht its name is new (null).
If you want javaClass2 print "Buddy", you should:
public javaClass2(String s) {
super(s);
String superTitle = super.getName();
System.out.println("HEY " + superTitle);
}
jv and jv2 are totally two different objects in the memory.
After all that is the fundamental meaning of "new" operator in Java.
you have used "new" operator twice in your code.
So it means you have two completely different objects.
jv's name is set as "Bobby" but nobody has set a name for the second object jv2 !
Imagine this:
class Manager extends Employee
{
....
public void setPMPCertified(boolean b)
{
...
}
}
//Generally Software engineers
class Employee
{
....
public void setName(String n)
{
.....
}
}
Manager m1 = new Manager();
Employee e1 = new Employee();
m1.setName("Robert");
m1.setPMPCertified(true);
e1.setName("Raja");
Robert is a manager. Raja is a software engineer.
They are completely two different data (object) in the memory.
Just because manager extends employee Robert and Raja cannot become single object.
Look at the fact we have used the new operator twice to create two objects.
Please note manager does NOT have the setName method.
It comes from the parent (Employee).
setPMPCertified is only applicable to managers.
we don't care if a software engineer is PMP certified or not!! :)
I have the following structure
public class parent {
int value ;
}
public class child extends parent {
int childValue;
public child(){}
public child (int value){
this.childValue = value ; // this line cause ConstructorCallsOverridableMethod warning during object construction
}
}
Could you please advice how to solve this error ?
The PMD rule says:
Calling overridable methods during construction poses a risk of invoking methods on an incompletely constructed object and can be difficult to debug. It may leave the sub-class unable to construct its superclass or forced to replicate the construction process completely within itself, losing the ability to call super(). If the default constructor contains a call to an overridable method, the subclass may be completely uninstantiable. Note that this includes method calls throughout the control flow graph - i.e., if a constructor Foo() calls a private method bar() that calls a public method buz(), this denotes a problem.
Example:
public class SeniorClass {
public SeniorClass(){
toString(); //may throw NullPointerException if overridden
}
public String toString(){
return "IAmSeniorClass";
}
}
public class JuniorClass extends SeniorClass {
private String name;
public JuniorClass(){
super(); //Automatic call leads to NullPointerException
name = "JuniorClass";
}
public String toString(){
return name.toUpperCase();
}
}
Solution
Delete any call to overridable methods in the constructor or add the final modifier to that methods.
Perhaps you could follow follow Java's Naming Conventions and also make the Child class final
public final class Child extends Parent {
My head hurts from thinking about an elegant solution to the following problem. I have a parent class and several subclasses. My parent class declares and implements a method to retrieve properties, but the name of the property file is determined by the subclasses.
I'm only working with instances of the subclasses.
The method (implemented in the parent) should use the field values of the subclass, but since I'm using it in the parent class, I need to declare it there as well.
Now, every time I call the method from a subclass the field value of the parent class is used.
Some simple code to illustrate my problem (please keep in mind: it's not about functionality - more about the design). The subclass defining the field value I want to use:
public class SubClass extends Parent {
public static final String CONFIG_FILE = "subclass.properties"; // same problem with non-static
public SubClass() {
System.out.println(getProperty("somekey"));
}
}
and the parent class defining and implementing the method I want to use:
public class Parent {
public static final String CONFIG_FILE = "config.properties"; // same problem with non-static
public String getProperty(String key) {
Properties props = new Properties();
try {
props.load(new FileReader(new File(CONFIG_FILE)));
}
catch (IOException ioe) {
return null;
}
return props.get(key);
}
Since I'm calling getProperty(..) from the subclass, I would expect it to use the field value of the instance it is operating on ("subclass.properties"), but instead it's using the parent field value ("config.properties"). I got the same effect with non-static fields.
Looking at your code, you are using the Parent.CONFIG_FILE, in subclass you should use SubClass.CONFIG_FILE
Put this in your subclass. This will then return the properties for the subclass. This method would override the one in the parent class.
public String getProperty(String key) {
return CONFIG_FILE;
}
Incidently you are shadowing the variable.
Alternatively I would recommend passing in the variable name to the constructor and then have it call super.
public SubClass() {
super(SUB_CLASS_CONFIG);
}
and then have the Parent construtor something like
public Parent(String key) {
CONFIG_FILE = key;
}
then you will not have to override the method. The method can just return config in the parent. I would think carefully as to whether you want it to be static though....
Just override (ie implement) getProperty() in the subclass.
When a class extends another, it inherits all methods and variables of the superclass. Both methods and variables can be used differently in the subclass, if you define it differently in the subclass with the same signature.
Now Oracle distincts between overwriting and hiding (http://docs.oracle.com/javase/tutorial/java/IandI/override.html).
It says that an instance method overwrites its superclass's method, while a class method hides it.
"The distinction between hiding and overriding has important implications. The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass."
Lets assume I have 2 classes Yes and Maybe. Yes extends Maybe.
Maybe has String a.
class Maybe {
String a;
public static void printOut() {
System.out.println("Maybe");
}
public void printAndSet() {
a = "Maybe";
System.out.println(a);
}
}
class Yes extends Maybe {
public static void printOut() {
System.out.println("Yes");
}
pubilc void printAndSet() {
a = "Yes";
}
}
class Print{
public static void mail(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
Maybe.printOut();
Yes.printOut();
m.printAndSet();
y.printAndSet();
}
And I say: It will print out
maybe
yes
maybe
yes
But after I read the Oracle article I thought it would have to print out:
yes
yes
maybe
yes
Because the instance method overwrites its superclass method.
I'm quite sure I am right with the output, but I'm sure aswell, that Oracle knows
better so I'm thinking I just didn't understand the article.
It can't be true that when I call an instance method from an object of a superclass, that it uses the overwritten method.
So I do not understand why to distinguish overwriting and hiding!
Can someone help out?
Edit; Inserted code instead of describing the classes!
Static methods can't be overridden at all. They're not called polymorphically, since they don't act on an instance of the class, but on the class itself.
If you call Maybe.printOut(), it will call the static printOut() method defined in Maybe. The fact that there is also a method printOut() defined in Yes is irrelevant: those two methods have nothing in common, except their name.
Note that you could confirm or infirm your doubts by simply writing a program and executing it.
The problem with hiding methods only occurs when you start calling static methods on an instance of an object. This is very bad practice, and should never be done. If you don't respect this rule, and have the following:
Maybe m = new Maybe();
Maybe y = new Yes();
m.printOut(); // DON'T DO THAT: it should be Maybe.printOut();
y.printOut(); // DON'T DO THAT: it should be Maybe.printOut() or Yes.printOut();
the result will be maybe maybe, because in the case of static methods, what counts is not the concrete type of the objects (Maybe and Yes), but their declared type (Maybe and Maybe).
public class Parent {
public String test(){
return "p";
}
public static String testStatic(){
return "sp";
}
}
public class Child extends Parent {
public String test(){
return "c";
}
public static String testStatic(){
return "sc";
}
}
public class Demo{
public static void main(String[] args) {
Parent p =new Parent();
Child c = new Child();
Parent pc = new Child();
System.out.println(p.test());
System.out.println(c.test());
System.out.println(pc.test());
//Although this is not the correct way of calling static methods
System.out.println(p.testStatic());
System.out.println(c.testStatic());
System.out.println(pc.testStatic());
}
}
OUTPUT will be: - (static method vs instance method)
p
c
c
sp
sc
sp
Take the following example, based on your example:
public class SO11720216 {
static class Maybe {
public static void hidden() { System.out.println("static maybe"); }
public void overwritten() { System.out.println("instance maybe"); }
public void inherited() { hidden(); }
public void called() { overwritten(); inherited(); }
}
static class Yes extends Maybe {
public static void hidden() { System.out.println("static yes"); }
public void overwritten() { System.out.println("instance yes"); }
}
public static void main(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
m.called(); /* prints:
instance maybe
static maybe
*/
y.called(); /* prints:
instance yes
static maybe
*/
Yes.hidden(); /* prints: static yes */
y.hidden(); /* bad style! prints: static yes */
}
}
The call to overwritten will be overwritten by each derived class. So every method will use the implementation belonging to the current object. On the other hand, the call to hidden will always use the implementation of the defining class. Hence Maybe.called will always call Maybe.hidden, and never Yes.hidden. To call Yes.hidden, you'll have to do so from within a method in Yes, or using a qualified name.
To phrase this differently:
To overwrite a method means that whenever the method is called on an object of the derived class, the new implementation will be called.
To hide a method means that an unqualified call to that name (like the hidden() call in the inherited() method of my above example) in the scope of this class (i.e. in the body of any of its methods, or when qualified with the name of this class) will now call a completely different function, requiring a qualification to access the static method of the same name from the parent class.
Perhaps your confusion comes from the fact that you assumed overwriting to affect all calls to the method, even for objects of the base class.