Java constructor error in child class - java

class Person
{
String name = "No name";
public Person(String nm)
{
name = nm;
}
}
class Employee1 extends Person
{
String empID ="0000";
public Employee1(String id)
{ // Line 1
empID = id;
}
}
public class EmployeeTest
{
public static void main(String[] args) {
Employee1 e = new Employee1("4321");
Person p = new Person("Hello");
System.out.println(e.empID);
}
}
I get compilation error saying constructor Person in class Person cannot be applied to given types; required String found no arguments but I am passing arguments for both the parent and the child class when I create new object in main method. Unable to figure out why compilation error?

You need to properly create the parent class, passing it a name as the Person construtor requires:
public Employee1(String id) {
super("person name"); // create the parent
empID = id;
}
Or maybe something like:
public Employee1(String id, String name) {
super(name); // create the parent
empID = id;
}
public static void main(String[] args) {
Employee1 e = new Employee1("4321", "Hello");
// ...
}

Because constructor in child class implicitly calls the parameter-less constructor of it's immediate super class only if the default constructor does not explicitly call a superclass constructor so
public Employee1(String id)
{ // Line 1
empID = id;
}
will try to call constructor in super class as you have not called it explicitly so you can say your code will be like this
public Employee1(String id)
{
super(); // Line 1
empID = id;
}
but in you parent class there is no "no argument" constructor, so it is giving error like this.

The implicit super constructor Person() is undefined.
So you must explicitly invoke its parent constructor.

On the constructor of employee you must call first the constructor of person as in super(name); and then initialize the subclass
class Employee1 extends Person
{
String empID ="0000";
public Employee1(String id, String name)
{ // Line 1
super(name);
empID = id;
}
}

Related

Java: Issue building a zoo using inheritance

I am new to Java and I'm having an issue with inheritance. I'm working through an activity where I have a parent class (Animal) and child classes (Giraffe in this instance) which inherits the fields of the parent class. I was instructed to have a default constructor and a constructor that accepts parameters in both instances of the parent and child classes.
The issue that I'm encountering is that when I run printInfo() it is returning the default for species in the parent's default constructor ('species') and not the child class ('giraffe'). I had assumed that the Giraffe child class would inherit this parent class method, but it seems that something's not quite right here.
(Note that each of my classes are separate files)
Any assistance or pointers would be greatly appreciated.
// Parent class:
public class Animal {
String name;
String species;
int age;
// default constructor
public Animal() {
name = "name";
species = "species";
age = 0;
}
// constructor w/ parameters
public Animal(String name, String species, int age){
this.name = name;
this.species = species;
this.age = age;
}
// method for printing out animal info
void printInfo() {
System.out.println(name + ", " + species + ", " + age);
}
}
// Child class:
public class Giraffe extends Animal {
String species = "giraffe";
// default giraffe constructor
public Giraffe() {
super();
name = "Errol";
age = 0;
}
// giraffe constructor with parameters
public Giraffe(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
// Main class (calls printInfo method from Animal parent class)
public class ZooBuilder {
public static void main(String[] args) {
Giraffe one = new Giraffe("Mark", 23);
one.printInfo();
}
}
Prints: *Mark, species, 23*
Change the Giraffe constructor to call the full constructor
public Giraffe(String name, int age) {
super(name, "Giraffe", age);
}
Change the default to also be like the above

Compile time vs Runtime method binding [duplicate]

I have a basic inheritance situation with an overloaded method in the super class.
public class Person {
private String name;
private int dob;
private String gender;
public Person(String theName, int birth, String sex){
name = theName;
dob = birth;
gender = sex;
}
public void work(){
getWorkDetail(this);
}
public void getWorkDetail(Employee e){
System.out.println("This person is an Employee");
}
public void getWorkDetail(Person p){
System.out.println("This person is not an Employee");
}
}
The following Employee class extends the Person class above:
public class Employee extends Person {
String department;
double salary;
public Employee(String theName, int birth, String sex){
super(theName, birth, sex);
department = "Not assigned";
salary = 30000;
}
}
The main method simply creates an Employee object (both static and dynamic type) and calls .work() on it:
public static void main(String[] args){
Employee e1 = new Employee("Manager1", 1976, "Female");
e1.work();
}
This ends up printing
This person is not an Employee
Looking through this I had thought that since both the static and dynamic type of the object e1 is Employee it would call the overloaded method in Person that takes an Employee as a parameter. Since I am clearly wrong about this I opened a debugger assuming the reference to "this" at the line getWorkDetail(this) in the Person class must have morphed to it's super class. However this is not what I found.
Clearly at this point in the code this is an Employee object, however it still chose to execute the overloaded method getWorkDetail(Person p). Can anyone explain this behavior?
Unlike method overrides, method overloads are linked based on the static type. And in this case, getWorkDetail(this) in Person only knows about the Person type.
Method overloading is not designed to provide dynamic runtime behavior.
To take advantage of dynamic binding, you may need to redesign your code to override the methods, instead:
public static void main(String[] args) throws IOException {
new Employee("Manager1", 1976, "Female").getWorkDetail();
new Person("Manager1", 1976, "Female").getWorkDetail();
}
And modify behavior based on implementing classes. Of course, you can overload methods, as long as you take care of overriding the overloaded methods too, if required.
class Person {
private String name;
private int dob;
private String gender;
public Person(String theName, int birth, String sex) {
name = theName;
dob = birth;
gender = sex;
}
public void getWorkDetail() {
System.out.println("This person is not an Employee");
}
}
class Employee extends Person {
String department;
double salary;
public Employee(String theName, int birth, String sex) {
super(theName, birth, sex);
department = "Not assigned";
salary = 30000;
}
public void getWorkDetail() {
System.out.println("This person is an Employee");
}
}
The overload resolution happens during compile time, not at runtime.
So, when you call getWorkDetails(this), this is assumed to be a Person (which is the static type) and hence called the corresponding overload.
Note: Using this inside Employee class would have made it an Employee type. You can verify this by overloading work() in Employee like this.
class Employee extends Person {
...
public void work() {
getWorkDetails(this); // This should print "This person is an Employee"
}
}
Problem specific solution
In some languages parameters are resolved to their dynamic type, but not in java. The compiler already determines at compile time where your getWorkDetail(this); will go. this is of type Person, so getWorkDetail(Person e) is called. In your specific case the solution is quite obvious. As others have already pointed out, you'll need to override getWorkDetail() in the Employee class.
Resolving methods to their dynamic parameter types
To solve the general problem of resolving parameter types at runtime, using the instanceof operator should be avoided, as it usually leads to unclean code.
If you have two different classes, a solution as simple as stated above is no longer possible. In these cases you'll have to use the visitor pattern.
Consider the following classes:
public interface Animal {
default void eat(Food food) {
food.eatenBy(this);
}
void eatMeat(Meat meat);
void eatVegetables(Vegetables vegetables);
}
public class Shark implements Animal {
public void eatMeat (Meat food) {
System.out.println("Tasty meat!");
}
public void eatVegetables (Vegetables food) {
System.out.println("Yuck!");
}
}
public interface Food {
void eatenBy(Animal animal);
}
public class Meat implements Food {
public void eatenBy(Animal animal) {
animal.eatMeat(this);
}
}
public class Vegetables implements Food {
public void eatenBy(Animal animal) {
animal.eatVegetables(this);
}
}
Which you can call like this:
Animal animal = new Shark();
Food someMeat = new Meat();
Food someVegetables= new Vegetables();
animal.eat(someMeat); // prints "Tasty meat!"
animal.eat(someVegetables); // prints "Yuck!"
Following the visitor pattern calling Animal.eat will call Food.eatenBy, which is implemented by both Meat and Vegetables. Those classes will call the more specific eatMeat or eatVegetables method, which uses the correct (dynamic) types.
Call preference
class Foo {
static void test(int arg) { System.out.println("int"); }
static void test(float arg) { System.out.println("float"); }
static void test(Integer arg) { System.out.println("Integer"); }
static void test(int... arg) { System.out.println("int..."); }
public static void main(String[] arg) {
test(6);
}
}
The output will be int printed on console. Now you comment the first test() method and see what is the output coming.
This is the preference hirarchey in primitive data types. Now coming to derived types declare a class FooChild like this
class FooChild extends Foo {
}
and create two new methods in Foo like
static void testChild(Foo foo) { System.out.println("Foo"); }
static void testChild(FooChild fooChild) { System.out.println("FooChild"); }
then in main method try calling testChild like this testChild(new FooChild());.
getWorkDetail(this) does not know what the subclasses are. call getWorkDetail instead.

Which Overloaded Method is Called in Java

I have a basic inheritance situation with an overloaded method in the super class.
public class Person {
private String name;
private int dob;
private String gender;
public Person(String theName, int birth, String sex){
name = theName;
dob = birth;
gender = sex;
}
public void work(){
getWorkDetail(this);
}
public void getWorkDetail(Employee e){
System.out.println("This person is an Employee");
}
public void getWorkDetail(Person p){
System.out.println("This person is not an Employee");
}
}
The following Employee class extends the Person class above:
public class Employee extends Person {
String department;
double salary;
public Employee(String theName, int birth, String sex){
super(theName, birth, sex);
department = "Not assigned";
salary = 30000;
}
}
The main method simply creates an Employee object (both static and dynamic type) and calls .work() on it:
public static void main(String[] args){
Employee e1 = new Employee("Manager1", 1976, "Female");
e1.work();
}
This ends up printing
This person is not an Employee
Looking through this I had thought that since both the static and dynamic type of the object e1 is Employee it would call the overloaded method in Person that takes an Employee as a parameter. Since I am clearly wrong about this I opened a debugger assuming the reference to "this" at the line getWorkDetail(this) in the Person class must have morphed to it's super class. However this is not what I found.
Clearly at this point in the code this is an Employee object, however it still chose to execute the overloaded method getWorkDetail(Person p). Can anyone explain this behavior?
Unlike method overrides, method overloads are linked based on the static type. And in this case, getWorkDetail(this) in Person only knows about the Person type.
Method overloading is not designed to provide dynamic runtime behavior.
To take advantage of dynamic binding, you may need to redesign your code to override the methods, instead:
public static void main(String[] args) throws IOException {
new Employee("Manager1", 1976, "Female").getWorkDetail();
new Person("Manager1", 1976, "Female").getWorkDetail();
}
And modify behavior based on implementing classes. Of course, you can overload methods, as long as you take care of overriding the overloaded methods too, if required.
class Person {
private String name;
private int dob;
private String gender;
public Person(String theName, int birth, String sex) {
name = theName;
dob = birth;
gender = sex;
}
public void getWorkDetail() {
System.out.println("This person is not an Employee");
}
}
class Employee extends Person {
String department;
double salary;
public Employee(String theName, int birth, String sex) {
super(theName, birth, sex);
department = "Not assigned";
salary = 30000;
}
public void getWorkDetail() {
System.out.println("This person is an Employee");
}
}
The overload resolution happens during compile time, not at runtime.
So, when you call getWorkDetails(this), this is assumed to be a Person (which is the static type) and hence called the corresponding overload.
Note: Using this inside Employee class would have made it an Employee type. You can verify this by overloading work() in Employee like this.
class Employee extends Person {
...
public void work() {
getWorkDetails(this); // This should print "This person is an Employee"
}
}
Problem specific solution
In some languages parameters are resolved to their dynamic type, but not in java. The compiler already determines at compile time where your getWorkDetail(this); will go. this is of type Person, so getWorkDetail(Person e) is called. In your specific case the solution is quite obvious. As others have already pointed out, you'll need to override getWorkDetail() in the Employee class.
Resolving methods to their dynamic parameter types
To solve the general problem of resolving parameter types at runtime, using the instanceof operator should be avoided, as it usually leads to unclean code.
If you have two different classes, a solution as simple as stated above is no longer possible. In these cases you'll have to use the visitor pattern.
Consider the following classes:
public interface Animal {
default void eat(Food food) {
food.eatenBy(this);
}
void eatMeat(Meat meat);
void eatVegetables(Vegetables vegetables);
}
public class Shark implements Animal {
public void eatMeat (Meat food) {
System.out.println("Tasty meat!");
}
public void eatVegetables (Vegetables food) {
System.out.println("Yuck!");
}
}
public interface Food {
void eatenBy(Animal animal);
}
public class Meat implements Food {
public void eatenBy(Animal animal) {
animal.eatMeat(this);
}
}
public class Vegetables implements Food {
public void eatenBy(Animal animal) {
animal.eatVegetables(this);
}
}
Which you can call like this:
Animal animal = new Shark();
Food someMeat = new Meat();
Food someVegetables= new Vegetables();
animal.eat(someMeat); // prints "Tasty meat!"
animal.eat(someVegetables); // prints "Yuck!"
Following the visitor pattern calling Animal.eat will call Food.eatenBy, which is implemented by both Meat and Vegetables. Those classes will call the more specific eatMeat or eatVegetables method, which uses the correct (dynamic) types.
Call preference
class Foo {
static void test(int arg) { System.out.println("int"); }
static void test(float arg) { System.out.println("float"); }
static void test(Integer arg) { System.out.println("Integer"); }
static void test(int... arg) { System.out.println("int..."); }
public static void main(String[] arg) {
test(6);
}
}
The output will be int printed on console. Now you comment the first test() method and see what is the output coming.
This is the preference hirarchey in primitive data types. Now coming to derived types declare a class FooChild like this
class FooChild extends Foo {
}
and create two new methods in Foo like
static void testChild(Foo foo) { System.out.println("Foo"); }
static void testChild(FooChild fooChild) { System.out.println("FooChild"); }
then in main method try calling testChild like this testChild(new FooChild());.
getWorkDetail(this) does not know what the subclasses are. call getWorkDetail instead.

How to return an object from parent class with type of Impl class?

I want to provide all implementation classes a default method that initializes the parent fields with default values. So I don't have to redefine those initialization within each Impl class:
public abstract class Parent {
private String name;
public static Parent defaultParent() {
Parent parent = new Parent();
//fill default field values
parent.name = "default name";
return parent;
}
}
public class Child extends Parent {
}
Now I can call Child.defaultParent(). But that would return me an object of type Parent. Is it possible this way to having the object being a Child object implicit? So that the defaultParent method always returns a type of the implementation class?
Maybe with java 8, functional interfaces or similar?
Here's one way to do it with Java 8:
public abstract class Parent {
private String name;
public static <T extends Parent> T defaultParent(Supplier<T> constructor) {
T parent = constructor.get();
//fill default field values
parent.name = "default name";
return parent;
}
}
public class Child extends Parent {
}
You can call the static method like this:
Child c = Parent.defaultParent(Child::new);
Or you can just use a constructor overload instead of a static factory method:
public abstract class Parent {
private String name;
public Parent(boolean useDefaults) {
if (useDefaults) {
//fill default field values
this.name = "default name";
}
}
}
public class Child extends Parent {
public Child(boolean useDefaults) {
super(useDefaults);
}
public Child() {
super(false);
}
}
This is what constructors were made for.
abstract class Parent {
private String name;
protected Parent(String name) {
this.name = name;
}
protected Parent() {
this("default name");
}
}
class DefaultChild extends Parent {
public DefaultChild() { super(); }
}
class CustomChild extends Parent {
public CustomChild(String value) { super(value); }
}
Everything else is just a fancy init method which is inferior to constructors because you can for example no longer assign values to final fields.
abstract class Parent {
private String name;
protected void init() {
this.name= "default name";
}
// or
protected static void init(Parent parent) {
parent.name = "default name";
}
}

Java Inheritance... Confused

I have a abstract Parent class that has multiple children. I'd like the child to be able to have a variable that is the same for every instance of that child. I'd prefer not to pass a constructor to the child to tell it it's name because that just seems silly when it can be hardcoded. From what I've read doing the following "hides" the parents instance variable and doesn't work as I want.
public abstract class Parent {
public String name = "the parent";
public getName(name);
}
public class Child1 extends Parent {
public String name = "Jon";
}
public class Child2 extends Parent {
public String name = "Mary";
}
Child1 c = new Child1();
c.getName(); // want this to return "Jon", but instead returns "the parent".
To be clear, basically what I want is something like c.getClass().getName() but I don't want to have the result of that dependent on the Class name, but rather on a hardcoded value.
Thanks
You could declare an abstract method in the parent and have each child implement the method to return the appropriate name, like this:
public abstract class Parent {
public abstract String getName();
}
public class Child1 extends Parent {
private static final String NAME = "Jon";
public String getName() { return NAME; }
}
public class Child2 extends Parent {
private static final String NAME = "Mary";
public String getName() { return NAME; }
}
Depending on what you're actually trying for, there are a couple of solutions. One is to make the child classes provide the name to the parent:
public abstract class Parent {
protected Parent(String name) {
this.name = name;
}
public getName() {return name;}
}
public class Child1 extends Parent {
public Child1() {
super("Jon");
}
}
public class Child2 extends Parent {
public Child2() {
super("Mary");
}
}
Another is to use method inheritance like Isaac Truett suggests.
Create a static final String in each child that has your hard-coded name:
public class Child1 extends Parent
{
public static final String NAME = "Jon";
}
Use a method instead of a field (variable):
public abstract class Parent {
public String getName() {
return "the parent";
}
}
public class Child1 extends Parent {
public String getName() {
return "Jon";
}
}
public class Child2 extends Parent {
public String getName() {
return "Mary";
}
}
In Java, at least, you can only override methods, not variables.
Another option would be to have Parent's constructor take the name as a parameter. If you do this it's best if Parent is abstract and all of the constructors take the name parameter. Then subclasses are required to pass in the name, which would typically be done something like this:
public class Child1 extends Parent {
public Child1() {
this("Jon");
// ...
}
}
Actually, even with the method overriding approach, it's nice if Parent is abstract so you can make getName() abstract.
The reason why your call to getName() doesn't return the child's name is because you've created a new variable call name within the child. Try this:
public class Child3 extends Parent{
public String name = "Jon";
public String getNames(){
return super.name + " : " + name;
}
}
You will see:
the parent : Jon
The correct way to set the name of the child into the parent's name variable is to say:
super.name = "Jon";
You need to overwrite the getName function in order to get the result you want.
Because the new String name is not replacing the parent name so the getName function is actually reading the parent String
Why not use the constructors?
public abstract class Parent {
public String name = "the parent";
public String getName() {
return name;
}
public void setName(String s){
name = s;
}
}
public class Child1 extends Parent {
public Child1() {
setName("Jon");
}
}
public class Child2 extends Parent {
public Child2() {
setName("Mary");
}
}
Child1 c = new Child1();
c.getName();
// Prints 'Jon'
You could do this using Java Reflection... but it's not a very clean way of doing things:
public abstract class Parent {
public String name = "the parent";
public String getName() throws Exception { return getClass().getField("name").get(this).toString(); }
}
Although I think Isaac's approach is the best way to approach the solution.

Categories

Resources