Java: Inherited class constructor is calling Super class - java

While creating a java program i encountered a problem,
A subclass constructor is throwing an Error by calling the Superclass's method
The code is similar to this :
class Manage
{
public static void main(String[] args)
{
Manager m1 = new Manager ( 35 );
}
}
class Employee
{
int emp_id;
public Employee(int id)
{
this.emp_id = id;
}
public int get_id()
{
return emp_id;
}
}
class Manager extends Employee
{
public Manager(int id )
{
this.emp_id = id ;
}
}
class Engineer extends Employee
{
public Engineer(int id)
{
this.emp_id = id ;
}
}
And the error is something like this :
$ javac app.java
app.java:25: cannot find symbol
symbol : constructor Employee()
location: class Employee
{
^
app.java:33: cannot find symbol
symbol : constructor Employee()
location: class Employee
{
^
2 errors
Why does this happen ?

The superclass doesn't have a default constructor. So you need to pass the appropriate constructor arguments to the superclass:
super(id);
(Put this as the top line in both the Manager and Engineer constructors.) You should also remove the this.emp_id = id line, in both cases.
In general, if your constructor doesn't start with a super(...) or this(...) statement (and you can only have one of these, not both), then it defaults to using super() (with no arguments).

Since you have specified a constructor with arguments, Java does not provide with a default constructor without arguments. You should create one yourself, or explicitly call the constructor you have created, by using super(id) as first line in the extended classes constructors.

The error is generated since you didn't define a default constructor (no arguments) in Employee
class Employee {
private int emp_id;
public Employee() {
}
public Employee(int id) {
this.emp_id = id;
}
public int get_id() {
return emp_id;
}
}
but there are a couple of points to consider: you are setting emp_id via the constructor and defined a getter to read it. It seems that the field was meant to be private. Otherwise you can just access directly.
You already have a constructor in Employee setting the ID no need to define the same constructor in the same class. Just use the constructor of the superclass.
class Manager extends Employee {
public Manager(int id ) {
super(id); // calls the superclass constructor
}
}
In this case you don't need the default constructor.

In java, a sub class constructor always calls one of its parent class's constructor. This is neccessary for the class to be initialized properly. Even when it is subclassed, the fields and state must be setup and this is how its done in java. If none is explicitly specified, it is calling the default no-arg constructor.

Related

A elegant way to implement ID on a abstract class

I have an abstract class. I want that every instance has a unique ID. I have implemented:
public abstract class MyAbstractClass{
static AtomicInteger nextId = new AtomicInteger();
private int id;
public MyAbstractClass() {
id = nextId.incrementAndGet();
}
}
public class MyClass extends MyAbstractClass {
public MyClass(){
super();
}
}
This approach works except the part there is nothing forcing the subclass to call the constructor.
Is there a way to implement a global ID for an abstract class?
there is nothing forcing the subclass to call the constructor.
There is nothing you can do to stop the subclass from calling super() unless parent constructors are built hierarchically wrong.
By "hierarchically wrong", I meant there is a parent constructor that isn't based on its no-argument constructor. For instance,
public MyAbstractClass() {
id = nextId.incrementAndGet();
}
public MyAbstractClass(String s) {
// ignores to call this();
}
Otherwise, any child will eventually call super(), and, thus, trigger your id initialisation.

Does a subclass use parent constructor if one isn't defined in the subclass? [duplicate]

This question already has answers here:
Why is super class constructor always called [duplicate]
(3 answers)
Closed 3 years ago.
If I have a subclass that doesn't have a constructor defined but in the superclass there is one defined, will the subclass use that constructor when the subclass object is instantiated?
Does a subclass use parent constructor if one isn't defined in the subclass?
That depends on what you mean by "use." If you mean, does the default constructor for a child class call the parent constructor, then yes, it does (more below). If you mean, is a default constructor matching whatever parameters the parent constructor has created automatically, then no, not in the general case.
When you don't declare any constructors for a child class, the default constructor is supplied for you. It always looks like this
/*same access modifier as the class*/ Child() {
super();
}
Base classes have a default as well, which looks the same but just doesn't have super();.
So if the parent class has a no-arguments constructor (explicitly, or via the default) then the child class's default constructor will successfully use it. But if there's a constructor defined in the parent class that requires an argument, then the child class won't compile, because the super() in the default constructor doesn't match a constructor in the parent class.
Compare this, which works:
public class Parent {
public Parent() { // I could have left this off, since it's the default for a
} // base class; it's here for emphasis
public static void main(String[] args) {
new Child();
}
}
class Child extends Parent {
}
with this (added a String param to the Parent constructor), which fails:
public class Parent {
public Parent(String s) {
}
public static void main(String[] args) {
new Child();
}
}
class Child extends Parent {
}
The second one fails with:
class Child extends Parent {
^
required: String
found: no arguments
reason: actual and formal argument lists differ in length
1 error
If no constructor is written in a class, actually a default constructor is added, which can be seen in the byte code:
class A {
}
will generate code for:
class A extends Object {
A() {
super();
}
}
Every constructor must call a constructor of the parent class as the first statement.
Again here there is an implicit call to super().
class B extends A {
B() {
System.out.println();
}
B(int n) {
System.out.println();
}
}
will generate code for
class B extends A {
B() {
super(); // A()
System.out.println();
}
B(int n) {
super(); // A()
System.out.println();
}
}
This means one can get an error, that no (overloaded) constructor is available for the given argument types.
An other point is, that in general the statement super(); serves no purpose.
Say you have an empty child class that extends the parent:
public class TestChild extends TestParent{
}
And the parent looks like:
public class TestParent {
private String testStr;
public TestParent() {
this.testStr = "I exist in the child class!";
}
public String getTestStr() {
return testStr;
}
public void setTestStr(String testStr) {
this.testStr = testStr;
}
}
And you create an object of the child in the main and print it out with:
TestChild test = new TestChild();
System.out.println(test.getTestStr());
The result will print out:
I exist in the child class!
This happens because the child class will automatically call the no-arg constructor of the super class. So you do not explicitly need a constructor in the child class as it will automatically generate to you a default constructor.

Beginner Q: optional arguments in Java

I'm totally new to Java, as in, I started yesterday.
I've got a class that I'd like to have two constructors for: one without arguments, and one with.
Supposedly this should be simple: overload the constructor by writing two methods:
public class sortList {
public int ncell, npart, cell_n, index, Xref;
// constructor(s):
public void sortList() {
initLists( 1, 1 );
}
public void sortList( int ncell_in, int npart_in ) {
initLists( ncell_in, npart_in );
}
private void initLists( int ncell_in, int npart_in ) {
/* DO STUFF */
}
}
When I call this from my main() though:
sortList mySL = new sortList( 5, 6 );
... java complains:
myDSMC.java:5: error: constructor sortList in class sortList cannot be applied to given types;
sortList mySL = new sortList( 5, 6 );
^ required: no arguments
found: int,int
reason: actual and formal argument lists differ in length
1 error
(For the curious, I am just translating a super-simple DSMC code from C++...).
What silly thing am I missing?
Thanks.
-Peter
This are not constructors, they are regular methods :
public void sortList() {...}
public void sortList( int ncell_in, int npart_in ) {...}
Change them to constructors by removing the return type :
public sortList() {...}
public sortList( int ncell_in, int npart_in ) {...}
Since you didn't declare any constructors in your sortList class (you just declared two regular methods having the same name as the class), only the default parameter-less constructor was available.
Constructors in Java have no return type and have name the same as the name of the class.
The all methods in java have return type (void - if nothing to return).
You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors. This default constructor will call the no-argument constructor of the superclass. In this situation, the compiler will complain if the superclass doesn't have a no-argument constructor so you must verify that it does. If your class has no explicit superclass, then it has an implicit superclass of Object, which does have a no-argument constructor.
Example of constructor and methods:
// for this class default no-args constructor implicitly created
public class Test1 {
int id;
// regular method
public int getId() {
return id;
}
// regular method
public int test1() {
return 1;
}
}
public class Test2 {
int id;
// no-args constructor
public Test2() {
}
// overloaded constructor
public Test2(int id) {
this.id = id;
}
// regular method
public int getId() {
return id;
}
// regular method
public void test2() {
System.out.println("1");
}
}
All defined constructors implicitly call super();. So Test2 constructor actually looks like this:
public Test2(int id) {
super();
this.id = id;
}

How to return the value of a super variable?

I'm writing program that demonstrates the use of inheritance and I have created a variable using the super() keyword. I am now trying to place the value of that variable into a new method that calls it so that I can call that method in my main method to use its value within other classes.
Here is the relevant code:
Food class (super class)
public class Food {
//field that stores the name of the food
public String name;
//constructor that takes the name of the food as an argument
public Food(String name){
this.name = name;
}
public String getName() {
return name;
}
}
Meat class (sub class with super keyword)
public class Meat extends Food
{
public Meat() {
super("Meat");
}
public String getName() {
return //get super() value??;
}
}
Main class
public class Main {
public static void main(String[] args)
{
Wolf wolfExample = new Wolf();
Meat meatExample = new Meat();
System.out.println("************Wolf\"************");
System.out.println("Wolves eat " + meatExample.getName());
}
}
Any help is appreciated, thanks.
You could just do
public String getName() {
return super.getName();
}
Although you don't even need to override the method in the first place, because you declared the field name in super class to be public which means it can be accessed from anywhere.
Don't override public String getName() in Meat class.
The inheritance allows to inherit public and protected methods of Food in all subclasses of Food, therefore in Meat.
So Meat which IS a Food has by definition this behavior :
public String getName() {
return name;
}
which returns the name field stored in the parent class.
Overriding a method in subclass to write exactly the same code than in the parent method is useless and should not be done because it is misleading. A person which reads the code will wonder : why having overrided the method in the child class if it does the same thing than the parent class ?
Edit
Besides, if you want to access a field declared in a super class from a subclass, you should :
provide a public getter in the super class if the field is private. Here :
public String getName() {
return name;
}
use directly the field in the subclass if the field has the protected modifier.
As a general rule, you should avoid declaring instance fields with the modifier public because by default properties of a object should be protected and you should provide methods to modify the field only if needed.
So, declaring your Food class like that seems more suitable :
public class Food {
//field that stores the name of the food
private String name;
//constructor that takes the name of the food as an argument
public Food(String name){
this.name = name;
}
public String getName() {
return name;
}
}
In your Meat class, imagine you would like to add an additional information in the string returned by getName(), you could override it and why not using the field from the super class :
public class Meat extends Food {
public Meat() {
super("Meat");
}
#Override
public String getName() {
return super.getName + "(but don't abuse it)";
}
}
Here overriding the method is helpful because the behavior of the method in the child class differs from which one definedin the super class.
Simply write:
public String getName() {
return name;
}
This is because when searching for a variable named name, Java proceeds in this order:
Local variables (none)
Current class's fields (none)
Superclass's fields (found)
Super-super-class's fields (etc.)
However, you didn't need to override getName() in the subclass in the first place. If you didn't define it, then it would inherit the superclass's implementation, which corresponds exactly to the behavior you wanted. Thus you were doing extra work for no gain.
The other answers showed you how to do what you want.
But you should't do it (in real life projects)!
The most important principle in object oriented programming is encapsulation (aka information hiding). This means that the internal structure of a class should not be visible or accessible to the outside.
Therefore all member variables should be private.
Also you should avoid setter/getter methods since they just redirect the access. (except the class is a DTO without any logic of its own).
Since food class has the method getName declared as public do
public String getName() {
return super.getName();
}

Java error: Implicit super constructor is undefined for default constructor

I have a some simple Java code that looks similar to this in its structure:
abstract public class BaseClass {
String someString;
public BaseClass(String someString) {
this.someString = someString;
}
abstract public String getName();
}
public class ACSubClass extends BaseClass {
public ASubClass(String someString) {
super(someString);
}
public String getName() {
return "name value for ASubClass";
}
}
I will have quite a few subclasses of BaseClass, each implementing the getName() method in its own way (template method pattern).
This works well, but I don't like having the redundant constructor in the subclasses. It's more to type and it is difficult to maintain. If I were to change the method signature of the BaseClass constructor, I would have to change all the subclasses.
When I remove the constructor from the subclasses, I get this compile-time error:
Implicit super constructor BaseClass() is undefined for default constructor. Must define an explicit constructor
Is what I am trying to do possible?
You get this error because a class which has no constructor has a default constructor, which is argument-less and is equivalent to the following code:
public ACSubClass() {
super();
}
However since your BaseClass declares a constructor (and therefore doesn't have the default, no-arg constructor that the compiler would otherwise provide) this is illegal - a class that extends BaseClass can't call super(); because there is not a no-argument constructor in BaseClass.
This is probably a little counter-intuitive because you might think that a subclass automatically has any constructor that the base class has.
The simplest way around this is for the base class to not declare a constructor (and thus have the default, no-arg constructor) or have a declared no-arg constructor (either by itself or alongside any other constructors). But often this approach can't be applied - because you need whatever arguments are being passed into the constructor to construct a legit instance of the class.
For those who Google for this error and arrive here: there might be another reason for receiving it. Eclipse gives this error when you have project setup - system configuration mismatch.
For example, if you import Java 1.7 project to Eclipse and you do not have 1.7 correctly set up then you will get this error. Then you can either go to Project - Preference - Java - Compiler and switch to 1.6 or earlier; or go to Window - Preferences - Java - Installed JREs and add/fix your JRE 1.7 installation.
It is possible but not the way you have it.
You have to add a no-args constructor to the base class and that's it!
public abstract class A {
private String name;
public A(){
this.name = getName();
}
public abstract String getName();
public String toString(){
return "simple class name: " + this.getClass().getSimpleName() + " name:\"" + this.name + "\"";
}
}
class B extends A {
public String getName(){
return "my name is B";
}
public static void main( String [] args ) {
System.out.println( new C() );
}
}
class C extends A {
public String getName() {
return "Zee";
}
}
When you don't add a constructor ( any ) to a class the compiler add the default no arg contructor for you.
When the defualt no arg calls to super(); and since you don't have it in the super class you get that error message.
That's about the question it self.
Now, expanding the answer:
Are you aware that creating a subclass ( behavior ) to specify different a different value ( data ) makes no sense??!!! I hope you do.
If the only thing that is changes is the "name" then a single class parametrized is enough!
So you don't need this:
MyClass a = new A("A");
MyClass b = new B("B");
MyClass c = new C("C");
MyClass d = new D("D");
or
MyClass a = new A(); // internally setting "A" "B", "C" etc.
MyClass b = new B();
MyClass c = new C();
MyClass d = new D();
When you can write this:
MyClass a = new MyClass("A");
MyClass b = new MyClass("B");
MyClass c = new MyClass("C");
MyClass d = new MyClass("D");
If I were to change the method signature of the BaseClass constructor, I would have to change all the subclasses.
Well that's why inheritance is the artifact that creates HIGH coupling, which is undesirable in OO systems. It should be avoided and perhaps replaced with composition.
Think if you really really need them as subclass. That's why you see very often interfaces used insted:
public interface NameAware {
public String getName();
}
class A implements NameAware ...
class B implements NameAware ...
class C ... etc.
Here B and C could have inherited from A which would have created a very HIGH coupling among them, by using interfaces the coupling is reduced, if A decides it will no longer be "NameAware" the other classes won't broke.
Of course, if you want to reuse behavior this won't work.
You could also get this error when JRE is not set. If so, try adding JRE System Library to your project.
Under Eclipse IDE:
open menu Project --> Properties, or right-click on your project in Package Explorer and choose Properties (Alt+Enter on Windows, Command+I on Mac)
click on Java Build Path then Libraries tab
choose Modulepath or Classpath and press Add Library... button
select JRE System Library then click Next
keep Workspace default JRE selected (you can also take another option) and click Finish
finally press Apply and Close.
Another way is call super() with the required argument as a first statement in derived class constructor.
public class Sup {
public Sup(String s) { ...}
}
public class Sub extends Sup {
public Sub() { super("hello"); .. }
}
I have resolved above problem as follows:
Click on Project.
click on properties > Java Build Path > Library > JRE System Library > Edit
Select default system JRE And Finish
Apply and close.
Eclipse will give this error if you don't have call to super class constructor as a first statement in subclass constructor.
Sorry for necroposting but faced this problem just today. For everybody also facing with this problem - one of he possible reasons - you don't call super at the first line of method. Second, third and other lines fire this error. Call of super should be very first call in your method. In this case everything is well.
Short answer:
Add a constructor with no argument in base/parent/super class. i.e for example,
class Parent{
String name;
int age;
String occupation;
//empty constructor
public Parent(){
}
public Parent(String name, int age, String employment){
this.name = name;
this.age = age;
this.occupation = employment;
}
}
// You can have any additional constructors as you wish aka constructor overloading here in parent class.
If a super class does not have the no-argument constructor then you will get the compile-time error. Object does have such the constructor, so if Object is a only super class then there is no problem.
// then let's inherit
class Child extends Parent{
Child(String name, int age){
this.name = name;
this.age = age;
}
}
With super(), a super class no-argument constructor is called and with super(parameter list), a super class constructor with the matching parameter list is called.
Here is simple example
public class A {
public A(int i){
//
}
}
class B extends A {
public B(int i){
super(i);
}
}
You can solve this error by adding an argumentless constructor to the base class (as shown below).
Cheers.
abstract public class BaseClass {
// ADD AN ARGUMENTLESS CONSTRUCTOR TO THE BASE CLASS
public BaseClass(){
}
String someString;
public BaseClass(String someString) {
this.someString = someString;
}
abstract public String getName();
}
public class ACSubClass extends BaseClass {
public ASubClass(String someString) {
super(someString);
}
public String getName() {
return "name value for ASubClass";
}
}
I had this error and fixed it by removing a thrown exception from beside the method to a try/catch block
For example:
FROM:
public static HashMap<String, String> getMap() throws SQLException
{
}
TO:
public static Hashmap<String,String> getMap()
{
try{
}catch(SQLException)
{
}
}

Categories

Resources