Does Java call an abstract classe's constructor automatically? - java

Say I've made an abstract class called animal, and then I make a subclass called dogs which extends animal. The animal class has a constructor method written inside. If I decide to instantiate a "dog" object, will the animal classes's constructor automatically be called as well?
If someone could clarify, and further expand on this a bit, it'd be greatly appreciated!

Yes , The constructor of an abstract class can be called. why not? Use super() from subclass to call the super class argument constructor(s). If you dont use super(), then by default the no-arg constructor of super class will be called.
If you call
Dog dog = new Dog();
By default the super class default constructor[no-arg constructor] will be called.
If you call
Dog dog = new Dog("doggie1");
Unless you explicitly call super() inside the one argument constructor of Dog, the default super class constructor will not be called.
Try it..
Edit: If you don't call super() inside the one argument constructor of Dog, then also the default super class constructor will be called.
If you want to explicitly call the argument constructor , say one argument constructor of the super class, you have to explicitly make the call super("value");
Animal() {
System.out.println("Animal superconstructor");
}
Edit 02:
Sample program and output
(1)
public class SubClass extends SuperClass {
SubClass(String str) {
super(str);
}
SubClass() {
}
public static void main(String[] args) {
new SubClass("hello");
}
}
abstract class SuperClass {
SuperClass() {
System.out.println("I am SuperClass()");
}
SuperClass(String str) {
System.out.println("I am SuperClass(String str)");
}
}
//output: I am SuperClass(String str)
(2)
public class SubClass extends SuperClass {
SubClass(String str) {
}
SubClass() {
}
public static void main(String[] args) {
new SubClass("hello");
}
}
abstract class SuperClass {
SuperClass() {
System.out.println("I am SuperClass()");
}
SuperClass(String str) {
System.out.println("I am SuperClass(String str)");
}
}
//output: I am SuperClass()
(3)
public class SubClass extends SuperClass {
SubClass(String str) {
}
SubClass() {
}
public static void main(String[] args) {
new SubClass();
}
}
abstract class SuperClass {
SuperClass() {
System.out.println("I am SuperClass()");
}
SuperClass(String str) {
System.out.println("I am SuperClass(String str)");
}
}
// output: I am SuperClass()

If Animal has a no-arg constructor, then Animal's subclasses will call it automatically. Otherwise, the compiler will complain. In such a case, you have to call super() explicitly with the appropriate parameters for the Animal constructor you wish to use.

If I remember correctly, the abstract class's constructor (only the default constructor) is called by default only in the instance of the default constructor. To call the other constructors of the inherited class, a super() call needs to be made inside the constructors of the subclass.

Related

Java inheritance: What is the difference between method overriding and method hiding? [duplicate]

This question already has answers here:
Overriding vs Hiding Java - Confused
(17 answers)
Closed last year.
According to the documentation
An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method.
While in case of static methods
If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.
So, I have tested the code example shown there with addition of more use cases:
The super class Animal:
public class Animal {
public static void testClassMethod() {
System.out.println("The static method in Animal");
}
public void testInstanceMethod() {
System.out.println("The instance method in Animal");
}
}
The subclass Cat:
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The static method in Cat");
}
public void testInstanceMethod() {
System.out.println("The instance method in Cat");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal animal = new Animal();
Animal.testClassMethod();
Cat.testClassMethod();
animal.testInstanceMethod();
myAnimal.testInstanceMethod();
}
}
The output here is:
The static method in Animal
The static method in Cat
The instance method in Animal
The instance method in Cat
So, I still see no actual difference between overriding the superclass instance method with subclass instance method with the same signature and overriding (hiding) the superclass static (class) method with subclass static method with the same signature.
What am I missing here?
Hiding it means that you can't call super.method() in the sub class's implementation.
So for example
class Cat extends Animal {
public static void testClassMethod() {
super.testClassMethod(); //this is not possible
System.out.println("The static method in Cat");
}
public void testInstanceMethod() {
super.testInstanceMethod(); //this is fine
System.out.println("The instance method in Cat");
}
}
You can call super() in an object method (not static), but you can not call super in a static method because there is no "super" object to call to.

Access shadowed methods based on the casting type of the object

Method calls are always determined based on the runtime type of the object, however how can I call shadowed methods of base classes from an inherit instance?
class Base {
String str = "base";
String str() { return str; }
}
class Impl extends Base {
String str = "impl";
String str() { return str; }
}
class Test {
public static void main(String[] args) {
System.out.println(((Base) new Impl()).str); // print 'base'
System.out.println(((Base) new Impl()).str()); // print 'impl'
}
}
For example above, how can I call the str() method of Base class from an Impl instance, preferably without using reflection?
Using the Keyword super
Accessing Superclass Members
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super. You can also use super to refer to a hidden field (although hiding fields is discouraged). an example below.
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
calling printMethod since child class
Here is a subclass, called Subclass, that overrides printMethod():
public class Subclass extends Superclass {
// overrides printMethod in Superclass
public void printMethod() {
super.printMethod();
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
if you want to read more
https://docs.oracle.com/javase/tutorial/java/IandI/super.html

How to call default constructor of an abstract class in Java

I tried to research over this topic but could not find a clarity over this. Please help me in this.
In the constructor of a child-class you can call
super(/*params if needed*/);
in order to call its parent's constructor
You can use super() in your child class. You cannot create instance of abstract class(you might know that)
abstract class Parent{
Parent(){
System.out.println("Parent contructor!");
}
}
public class Child extends Parent{
public Child() {
super();
System.out.println("Child contructor!");
}
public static void main(String[] args) {
new Child();
}
}
Even if you do not specify super() in Child class, still the parent class constructor will be called because super() will be put by compiler in default constructor of Child class while generating the .class. If you only have parameterized constructor in Parent class then you will have to explicitly call the parent class constructor by super(..parameter) in your child class constructor . Hope this helps!
Something like this :
abstract class MyClass{
int val;
public MyClass( int val) {
this.val= val;
}
}
class Test extends MyClass{
public Test () {
super(2);
}
}
While you may not call upon a default constructor for an Abastract class, you can invoke the default constructor for the sub-class that embodies your abstract class.
For example:
abstract class Animal {
public Animal (){ ... }
abstract public String sound();
}
class Horse extends Animal{
public Horse(){
super()
}
#Override
public String sound(){
return "neigh";
}
}
class Dog extends Animal{
public Dog(){
super()
}
#Override
public String sound(){
return "woof";
}
}
It is not directly possible to make a new Animal. You can make new Dog-s and Horse-s with annomyously for (common) Type Animal example:
public Animal makeAnimals( Animal existingCreature )
throws InstantiationException, IllegalAccessException
{
return existingCreature.getClass.newInstance();
}
Will make a new instance of the concrete class you provided:
Dog fido = new Dog();
Horse hack = new Horse();
Dog puppy = makeAnimals( fido ); // new uninitialised Dog instance
Horse foal = makeAnimals( hack ); // new uninitialised Horse instance
Alternatively you can make an annomyous instance
Animal parrot = new Animal() {
#Override
public String sound(){
return "squawk";
}
}
As a way to make new animal types. If you were doing something for real like Animals it would probably be better to make a Parot subclass.

Java calling Super constructor confusion

class Yfk {
public static void main(String[] args) {
System.out.println(new YfkC().x);
}
}
abstract class YfkA {
int x = 3;
YfkA() { x++; }
}
class YfkB extends YfkA {}
class YfkC extends YfkB {}
The final result is 4. I am not clear about the extend process. In the main function, we create an object YfkC and invoke Yfkc.x. My understanding is since there is no method and filed in class yfkc, so we find in yfkb, and then find in yfkc. At this time, will YfkC be upcasted to YfkA automatically? Equal System.out.println(new YfkA().x); so we will get x = 4; I am confused about the process from YfkC to YfkA.
new YfkC().x
This internally calls the constructor of the sub class. so the value of x is incremented and printed as 4.
YfkC() -> YfkB() -> YfkA() { x++;};
The default constructor of each class is calling the super();. This calls the default constructor of the super class before executing it's own.
If you want to know about the constructor chaining then put as system out and see the calling chain.
public class Yfk {
public static void main(String[] args) {
System.out.println(new YfkC().x);
}
}
abstract class YfkA {
int x = 3;
YfkA() {
System.out.println("YfkA");
x++; }
}
class YfkB extends YfkA {
public YfkB() {
System.out.println("YfkB");
}
}
class YfkC extends YfkB {
public YfkC() {
System.out.println("YfkC");
}
}
output:
YfkA
YfkB
YfkC
4
When you invoke any Child constructor. There is a chain call to the immediate parent class constructor from the current class. And the call continues until the Object class constructor invokes since that the possible most Parent classes super class is.
Here is an example how constructor behaves in inheritance
public class ParentClass {
public ParentClass() {
System.out.println("Parent default constructor invoked");
}
public ParentClass(int a) {
System.out.println("Parent argumented constructor invoked");
}
public static void main(String[] args) {
SubSubClass sub = new SubSubClass();
}
}
class SubClass extends ParentClass {
public SubClass() {// not calling any super
System.out.println("Child default constructor invoked");
}
public SubClass(int b) {
super(b);
System.out.println("Child default constructor invoked");
}
}
class SubSubClass extends SubClass {
public SubSubClass() {// not calling any super
System.out.println("Sub Child default constructor invoked");
}
public SubSubClass(int b) {
super(b);
System.out.println("Sub Child default constructor invoked");
}
}
OUTPUT:
Parent default constructor invoked
Child default constructor invoked
Sub Child default constructor invoked
I wrote an article covering this topic, hope that clears your doubt.
Constructor inheritance(ovveriding) and reasons behind restricting constructor inheritance in Java
Whenever a child class is instantiated, its parent constructors are invoked in sequence, up the chain.
In your hierarchy, you have:
YfkC
YfkB
abstract YfkA
Object
...and in each of their constructors, there is an implicit call to super().
So, new YfkC invokes YfkB's constructor, which invokes the abstract class's YfkAs constructor, which results in the incrementation of x.
If you were to execute new YfkC().x again, you'd get 5, since every time you new up any of YfkA's children, you would be invoking that constructor.

Default and parameterize constructore

I am calling parametrized constructor of super class then also it is throwing compile time error such as no default constructor Why? Because as per the program i m not calling default constructor at all.
class Sup
{
public Sup(String s)
{
System.out.println("super");
}
}
class Sub extends Sup
{
public Sub()
{
System.out.println("sub class");
}
public static void main(String arg[])
{
Sup s2=new Sup("pavan");
}
}
You need to define the super classes default constructor, because unless otherwise specified the base classes constructor will try to call the super class, in your case the super class doesn't have a parameterless constructor so you'll get a compile error.
class Sup
{
public Sup(){}
public Sup(String s)
{
System.out.println("super");
}
}
class Sub extends Sup
{
public Sub()
{
System.out.println("sub class");
}
public static void main(String arg[])
{
Sup s2=new Sup("pavan");
}
}
Or make a explicit call to the super classes constructor(s) using super() and in your case for the parametrized constructor super("some string")
class Sup
{
public Sup(String s)
{
System.out.println("super");
}
}
class Sub extends Sup
{
public Sub()
{
super("some string");
System.out.println("sub class");
}
public static void main(String arg[])
{
Sup s2=new Sup("pavan");
}
}
Your Sub() constructor is calling default constructor (which is done implicitly if you don't call super() explictly or call another constructor in the same class in first line of your constructor) in Sup class which you did not provide. You should add a call to Sup(String s) in Sub() constructor or add default no-param constructor in your Sup class.

Categories