In the following code:
import java.io.*;
public class MyClass1
{
MyClass1()
{
System.out.println("base class");
}
public void print()
{
System.out.println("base print");
}
}
class ChildClass extends MyClass1
{
public ChildClass()
{
System.out.println("child class");
}
public void print()
{
System.out.println("child print");
}
}
Why is it that when I create an instance of type ChildClass the constructor of the base class is also executed??
Because your child class extends the base class - it's an instance of the base class and has all of the same fields and variables, etc. Thus the base class must also be instantiated.
For a concrete example, imagine your base class had the following in:
public class Base
{
final private int id;
public Base()
{
this(-1);
}
public Base(int id)
{
this.id = id;
}
public getId()
{
return id;
}
}
A final variable is guaranteed to be instantiated when the class is constructed. Your child class will have an id field (even if it cannot access it directly with child methods), and since this field is private you cannot possible instantiate it with the child constructor - so a base class constructor must be called.
Bear in mind that this isn't solely an issue with final variables, nor is it unique to any particular features you may use - since your child class is a base class, it needs to be properly instantiated as one.
Because that's what's supposed to happen :-)
Your derived class uses the base class as a foundation. In OO speak it is-a base class. That base class also needs to initialise itself, and consequently its constructor must be called.
It's not obvious from your example, but it will make more sense if you give your base class some (protected) members. Initialise them in the base constructor, and consequently they will have the expected values when viewed from your derived class upon construction.
See below. The field value is visible in the child class. What would you expect as the initialised value ?
public class MyClass1
{
protected int value;
MyClass1()
{
System.out.println("base class");
this.value = 42;
}
}
class ChildClass extends MyClass1
{
public ChildClass()
{
// what would you expect 'value' to be here ?
System.out.println("child class " + value);
}
}
Because compiler by default add super() constructor in the child class constructor if it is not specified . Every Constructor Should have either this() in case of without inheritance or super() method when ever there is an inheritance . To illustrate it i have taken this example .
public class Vehicle {
protected int wheels;
protected int lights;
Vehicle(){
System.out.println("Vehicle Class Constructor");
this.wheels=4;
this.lights=2;
}
}
Vehicle is the parent class
class Car extends Vehicle {
public Car(){
#Compiler add the super() constructor by default
System.out.println("Car class constructor");
}
}
Car is the Child class
public class TestCar {
public static void main(String args[]){
Car c = new Car();
System.out.println("Wheels" + c.wheels);
System.out.println("Lights" + c.lights);
}
}
In above code snippet When i compile the TestCar.java file during the Compile time the compiler looks for the Car constructor and checks whether Car class has any parent as soon as it checks that Car class extends the parent class Vehicle , it checks whether user had provided super() in inheritance tree . if not it adds one .
Hope this helps !
Related
Here is my base class:
#Service
public class BasicUserManagerService implements UserManager {
#Autowired
private UserRepository UserRepository;
private Logger logger = LoggerFactory.getLogger(UserManagerPasswordController.class);
#Override
public void createUser(User User) {
if (UserRepository.findByEmail(User.getEmail()) != null)
throw new InvalidDataException("User already registered with this email address");
UserRepository.save(User);
logger.info("Created user: {}", User.getEmail());
}
}
I am trying to extend this class as follows:
#Service
public class UserManagerService extends BasicUserManagerService implements UserManager {
#Override
public void createUser(User User) {
super().createUser(User);
}
}
But I keep getting the error that the call to super() must be the first statement in the constructor body.
As you can see I don't have a constructor and even when I add it, I get the same error. Why is this happening and how can I avoid it?
Change this super usage. super() is parent's constructor. super is a reference to the parent class.
#Service
public class UserManagerService extends BasicUserManagerService implements UserManager {
#Override
public void createUser(ProxyCircuitUser proxyCircuitUser) {
super.createUser(proxyCircuitUser);
}
}
super() is a call to the parent class constructor;
which is not at all what you want.
Instead, you want to call the parent class implementation of the createUser method.
The code for that is: super.createUser(user)
Here are various uses of Super Keyword in Java:
Use of super with variables
This scenario occurs when a derived class and base class has same data members. In that case there is a possibility of ambiguity for the JVM.
/* Base class vehicle */
class Vehicle
{
int maxSpeed = 120;
}
/* sub class Car extending vehicle */
class Car extends Vehicle
{
int maxSpeed = 180;
void display()
{
/* print maxSpeed of base class (vehicle) */
System.out.println("Maximum Speed: " + super.maxSpeed);
}
}
/* Driver program to test */
class Test
{
public static void main(String[] args)
{
Car small = new Car();
small.display();
}
}
Output:
Maximum Speed: 120
Use of super with methods
This is used when we want to call parent class method. So whenever a parent and child class have same named methods then to resolve ambiguity we use super keyword.
/* Base class Person */
class Person
{
void message()
{
System.out.println("This is person class");
}
}
/* Subclass Student */
class Student extends Person
{
void message()
{
System.out.println("This is student class");
}
// Note that display() is only in Student class
void display()
{
// will invoke or call current class message() method
message();
// will invoke or call parent class message() method
super.message();
}
}
/* Driver program to test */
class Test
{
public static void main(String args[])
{
Student s = new Student();
// calling display() of Student
s.display();
}
}
Output:
This is student class
This is person class
Use of super with constructors
super keyword can also be used to access the parent class constructor. One more important thing is that, ‘’super’ can call both parametric as well as non parametric constructors depending upon the situation.
/* superclass Person */
class Person
{
Person()
{
System.out.println("Person class Constructor");
}
}
/* subclass Student extending the Person class */
class Student extends Person
{
Student()
{
// invoke or call parent class constructor
super();
System.out.println("Student class Constructor");
}
}
/* Driver program to test*/
class Test
{
public static void main(String[] args)
{
Student s = new Student();
}
}
Output:
Person class Constructor
Student class Constructor
As super() will call the constructor of parent class, it should be the first statement to be executed in child class's constructor. If you want to call a method of parent class use super instead of super().
For More Info please read: super in java
For a particular program, I essentially have an abstract superclass with several different subclasses. However, I'm having trouble with field shadowing as illustrated below.
abstract class Super {
String name;
String getName() {
return name;
}
}
Now I create subclasses that each have their own "name".
class Sub extends Super {
name = "Subclass";
}
However, creating instances of the subclass, and then calling the inherited method getName() will yield null due to field shadowing.
Is there an easy way to avoid this problem, and to allow subclasses to each have a unique field that can be accessed by an inherited method?
Make the field visible in the child class and initialize it in the subclass constructor or in a subclass instance initializer.
You might try this mechanism (bonus left to reader, extend code to get the name of the class directly). The code use the Abstract classes constructor to set the name. You could also define a setName function in the Super class and use that.
Super class (abstract)
package stackShadow;
public abstract class Super {
String name;
public Super(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Shadow1 class first subclass
package stackShadow;
public class Shadow1 extends Super {
public Shadow1() {
super("Shadow1");
}
}
Shadow2 class second subclass
package stackShadow;
public class Shadow2 extends Super {
public Shadow2() {
super("Shadow2");
}
}
Test class to test getName
package stackShadow;
public class Test {
public static void main(String[] args) {
Shadow1 one = new Shadow1();
Shadow2 two = new Shadow2();
System.out.println("Name for one is: " + one.getName());
System.out.println("Name for two is: " + two.getName());
}
}
Lets say I have a class
public class Base {}
and a child class
public class Derived extends Base {
public void Foo(Object i){
System.out.println("derived - object");
}
}
and main class
public class Main {
public static void main(String[] args) {
Derived d = new Derived();
int i = 5;
d.Foo(i);
}
}
In console we will see
derived - object
Some time later I want to modify my superclass like this :
public class Base {
public void Foo(int i) {
System.out.println("base - int");
}
}
Now if I run my programm I will see:
base - int
So can I make a method in superclass not avaliable in my child class?
In result I want to see derived - object.
I see some don't understand what I want so I'll try to explain:
I want to modify only superclass and I don't want to modify my child class.. for example if I will make jar with my superclass and jar with my childs. I don't want to change all jars.. I want to add method into superclass and make it avaliable for superclass..
And such code
public class Main {
public static void main(String[] args) {
Derived d = new Derived();
int i = 5;
d.Foo(i);
Base b = new Base();
b.Foo(i);
}
}
give me
derived - object
base - int
You should use following signature for Foo method in base class:
public void Foo(Object i) {
System.out.println("base - int");
}
This way you can override method Foo from base class. Now you do not override this method but overload it instead.
If you want to use public void Foo(int i) signature in your base class then you can define Foo method in base class as private.
PS: I hope that I've understood you.
private members are limited to the class scope.
default (no keyword for this one) are limited to other members of the same package.
protected are limited to hierarchy.
public are not limited.
So if you don't want your child class to access a member of the superclass (member means methods, enum, variables ...) you should declare your foo like this :
public class Base {
private void Foo(int i) {
System.out.println("base - int");
}
}
Edit from my comment :
if you dont want child class to access a parent's member at compile time I can't see any way to still allow external classes to access it.
You want to block access from close scope while allowing broader scope. This can only be done by overriding the method and throwing an exception for accessviolation or something which is not at compile time but at runtime. Although you could make it work with a custom annotations but I don't know how to do this.
You can make a method final, which means, that the child class cannot override it.
If you do not do that and the child class overrides the method, you cannot call the super classes method from your main.
A Convention note: Please use lowercase method names in java.
package com.abc;
public class TestParentChild {
public static void main(String[] asd) {
Base b = new ChildB();
b.foo(5);
}
}
class Base {
public void foo(int i) {
System.out.println("derived - int");
}
}
class ChildB extends Base {
public void foo(int i) {
System.out.println("derived - object");
}
}
This might help you
I wanted to implement a method in a abstract class that is called by the inherited classes and uses their values.
For instance:
abstract class MyClass{
String value = "myClass";
void foo(){System.out.println(this.value);}
}
public class childClass{
String value="childClass";
void foo(){super.foo();}
}
public static void main(String[] args){
new childClass.foo();
}
This will output "myClass" but what I really want is to output "childClass". This is so I can implement a "general" method in a class that when extended by other classes it will use the values from those classes.
I could pass the values as function arguments but I wanted to know if it would be possible to implement the "architecture" I've described.
A super method called by the inherited class which uses the values from the caller not itself, this without passing the values by arguments.
You could do something like this:
abstract class MyClass {
protected String myValue() {
return "MyClass";
}
final void foo() {
System.out.println(myValue());
}
}
public class ChildClass extends MyClass {
#Override
protected String myValue() {
return "ChildClass";
}
}
and so on
This is a place where composition is better than inheritance
public class Doer{
private Doee doee;
public Doer(Doee doee){
this.doee = doee;
}
public void foo(){
System.out.println(doee.value);
}
}
public abstract class Doee{
public String value="myClass"
}
public ChildDoee extends Doee{
public String= "childClass"
}
...
//Excerpt from factory
new Doer(new ChildDoee);
I believe you are asking whether this is possible:
public class MyClass {
void foo() {
if (this instanceof childClass) // do stuff for childClass
else if (this intanceof anotherChildClass) // do stuff for that one
}
}
So the answer is "yes, it's doable", but very much advised against as it a) tries to reimplement polymorphism instead of using it and b) violates the separation between abstract and concrete classes.
You simply want value in MyClass to be different for an instance of childClass.
To do this, change the value in the childClass constructor:
public class childClass {
public childClass() {
value = "childClass";
}
}
Edited:
If you can't override/replace the constructor(s), add an instance block (which gets executed after the constructor, even an undeclared "default" constructor):
public class childClass {
{
value = "childClass";
}
}
I'm stuck with a Java OOP problem. I have come up with some toy code to explain the problem. Here are my classes -
Class 1 - Car.java
public class Car {
public void reportProblem(String problem){
ReportUtil.reportVehicleInfo("Car", 4, problem); //4 is number of wheels
}
//bunch of other methods
}
Class 2 - Truck.java
public class Truck {
public void reportProblem(String problem){
ReportUtil.reportVehicleInfo("Truck", 6, problem);
}
//bunch of other methods
}
Class 3 - ReportUtil.java
public class ReportUtil {
public static void reportVehicleInfo(String name, int wheels, String problem){
System.out.println(String.format("%s %s %s", name, wheels, problem));
}
}
Class 4 - Test.java
public class Test {
public static void main(String[] args) {
Car c = new Car();
c.reportProblem("puncture");
Truck t = new Truck();
t.reportProblem("engine missing");
}
}
I want to abstract the "reportProblem" method implementation in "Car" and "Truck" to a parent class. This is what I did -
Class 1 - Vehicle.java
public abstract class Vehicle {
public String mName;
public int mNumWheels;
public void reportProblem(String problem){
ReportUtil.reportVehicleInfo(mName, mNumWheels, problem);
}
public void setName(String name){
mName = name;
}
public void setNumWheels(int numWheels){
mNumWheels=numWheels;
}
}
Class 2 - Car.java
public class Car extends Vehicle {
//bunch of other methods
}
Class 3 - Truck.java
public class Truck extends Vehicle {
//bunch of other methods
}
Class 4 - ReportUtil.java (No change made to this class).
public class ReportUtil {
public static void reportVehicleInfo(String name, int wheels, String problem){
System.out.println(String.format("%s %s %s", name, wheels, problem));
}
}
Class 5 - Test.java
public class Test {
public static void main(String[] args) {
Car c = new Car();
c.setName("Car"); //NOTE : Can be missed!
c.setNumWheels(4); //NOTE : Can be missed!
c.reportProblem("puncture");
Truck t = new Truck();
t.setName("Truck"); //NOTE : Can be missed!
t.setNumWheels(6); //NOTE : Can be missed!
t.reportProblem("engine missing");
}
}
This achieves what I want (I have abstracted the implementation of "reportProblem"). But I know this is not the best way to do it. One reason is that the "reportProblem" method should not be called without calling "setName" and "setNumWheels" methods. Otherwise 'null' will be passed. Is there a way of enforcing, using some OOP technique, the two methods calls (setName and setNumWheels) BEFORE reportProblem is called?
I hope I have made myself clear. If I am not, just let me know how you would have done it so that I can learn from it.
Yes, make name and numWheels final and assign then in the constructor. So...
Class 1 - Vehicle.java
public abstract class Vehicle {
public final String mName;
public final int mNumWheels;
protected Vehicle(String name, int numWheels){
this.mName = name;
this.mNumWheels = numWheels;
}
public void reportProblem(String problem){
ReportUtil.reportVehicleInfo(mName, mNumWheels, problem);
}
...
}
Class 2 - Car.java
public class Car extends Vehicle {
public Car(){
super("Car", 4);
}
//bunch of other methods
}
Class 3 - Truck.java
public class Truck extends Vehicle {
public Truck(){
super("Truck", 6);
}
//bunch of other methods
}
Also, public fields are not good OO practice, because they expose details of your class' implementation that could be modified by users of the class. Those fields should be private. If the clients of the class need to know about them (or change them), then you should allow public getter (or setter) methods.
If you want to set the fields "required", you can set them as parameters in Truck/Car constructors and not provide a default constructor for these classes.
If members are essentials for an object's state/functionality, put them as part of a constructor, so it is not possible to create an object (and call the method of concern) without providing proper values for these members.
But you should not also provide a no-args constructor.
If there are too many parameters needed consider looking into the Builder idion
In addition to #Tony's answer (+1) if you have to use bean notation (default constructor and setters) and still do not want to allow using any business methods before the object is initialized you can do the following.
Define abstract method checkInitalized() in your Vehicle class. Implement this methods for your Car and Truck. BTW this method will probably have default implementation in Vehicle. In this case do not forget to call super from its overridden versions.
checkInitalized() should throw exception (e.g. IllegalStateException) if not all required fields are initialized.
Now call this method in the beginning of each business method. This will prevent you from using object that is not initialized yet.
This technique is a little bit verbose. Probably using wrapper pattern or AOP (e.g. AspectJ) may be useful here.