Lets say i have a Super class Person and subclass Employee
I would like to create a person class first and then use it as a param to be placed into my employee class's constructor.
E.g. Public Empolyee(Person person....) (This produces a constructor not found error during compile time)
My Case scenario is that i have a Person object that has not been instantiated as an employee yet and later on i would like to use it to instantiate an Employee object and I would like to pass this person's variables over.
So how do i do this? Also please do explain if it should be done this way or not.
You directly get access to all Person class members via Employee class due to the inheritance relationship. You dont need to pass parent object to a child.
Pass all the necessary parameters to Employee and call super() from its constructor.
//Person constructor
Person(param1, param2){
}
class Employee extends Person
//Employee constructor
Employee(param1, param2){
super(param1, param2);
}
// New object
Employee emp = new Employee(param1, param2);
Also constructor dont return anything so remove the void in your question.
Child class automatically gets access of all the public, protected members of the parent and child also has reference to parent class.
why you want to pass parent class reference to Child class. Instead you can call parent class constructor from child class like this:
public Child(){
super()
}
According to the question below, we can do this:
public class Child1 extends Super1 {
private int l;
public Child1(Super1 s){
super(s);
}
public Child1(){
this.l=20;
}
}
public class Super1 {
private int k;
public Super1(){
}
public Super1(Super1 s){
k=s.k;
}
}
i dont see your inheritance logic here correctly.
you have answer already..see below
class person()
class employee extends person(here)
hence you get to access its variables and methods..
just curious why you need to instantiate employee and injecting person class which is already parent to employee.
Your Employee will work as a person.You can call every method or variable (except private variables and methods) of Person by Employee object. But still if you want to pass a Person object to the constructor of Employee class then you can do it as fallows-
public Employee(Person person,.......){
super();//or pass required parameters according to constructor of Person class
//do whatever you want
}
it will work perfectly.
try this:
//if your Person constructor looks like this
public Person(param1, param2){
}
//then your copy constructor would look like this
public Employee(Person p){
super(p.getParam1 p.getParam2);
}
Related
I'm experiencing odd behavior while debugging my Java reflection homework in Eclipse.
I have 2 classes defined:
public class OuterClass{
protected Person person;
public void aPerson(Integer age) {
person = new Person(age);
}
}
public class OuterDerivedClass extends OuterClass {
public class InnerClass extends OuterClass {
public void aPerson(Integer age) {
person = new Person(age);
}
}
}
At some point in my program, I instantiated an InnerClass instance like so (using reflection as my program is supposed to work on any class. Nested classes could be either static/non-static and public/private/protected):
Class<?> outer_class = outer_instance.getClass();
Constructor<?> ctor = inner_class.getDeclaredConstructor(outer_class);
Object inner_instance = ctor.newInstance(outer_instance);
Later on I invoked the OuterDerivedClass$InnerClass.aPerson method:
method.invoke(inner_instance, parameter);
For now, it seemed like all went OK: The inner_instance was created successfully, the correct aPerson method (the one in InnerClass) was invoked. BUT, later on my program, as I tried to access the person field from outer_instance, I figured out it was still NULL (though it was created in aPerson method).
While debugging in Eclipse, I found out this:
(PersonStoryDerivedTest == OuterDerivedClass in my question).
The id of this$0 is the same as the one I sent to the constructor (outer_instance). I couldn't figure out what is the second person field (the one that apparently was created by invoking aPerson). Isn't this field supposed to exist only in the nesting class? My intention was that the invocation of OuterDerivedClass$InnerClass.aPerson would change the person field in outer_instance (I thought this is the reason why it was sent to the Constructor in the first place).
Can someone please clarify these issues? Thanks!
I couldn't figure out what is the second person field
Well, since
public class InnerClass extends OuterClass {
// ^^^^^^^^^^^^^^^^^^
your InnerClass also inherits its own person field which is set by
public void aPerson(Integer age) {
person = new Person(age);
}
because person refers to this.person and this inside this method represents instance of class where method was implemented (in InnerClass).
If you want your method to initialize OuterClass#person field you need to refer to it via OuterDerivedClass.this.person, but this will leave uninitialized person field of InnerClass.
Other (simpler) option is not extending OuterClass from InnerClass:
public class InnerClass{
So, I ran into a wall earlier. If I have a class Parent with an inner class SubParent like this:
public class Parent
{
public class SubParent
{
}
public Parent(SubParent sp)
{
}
}
Then I have a Child class which extends Parent like this:
public class Child extends Parent
{
public Child()
{
super(new SubParent());
}
}
Then I get a "error: cannot reference this before supertype constructor has been called" with an arrow pointing at the SubParent constructor.
Now, if I have SubParent as a separate class in it's own file, everything is fine. But I would like to have it as an inner class. Is there any way to do that?
An inner class instance requires an outer class instance to exist. At the point you are calling
super(new SubParent());
the SubParent constructor would have been called before an outer class instance has been created. You can't do this.
Either declare SupParent in its own file or make it static. What relationship are you trying to achieve anyway?
Since your SubParent is not a static nested class, there's an implicit relationship between it and the Parent object it belongs to (in this case, also a Child object). It sounds like you're not needing the relationship an inner class provides; try making SubParent a public static class.
Note that there's a distinction between an inner class, which is not static (has a reference to an instance of its containing class), and a nested class, which is any class contained inside another class, whether static or not.
Your problem is that you are trying to create a SubParent very early in construction of the Child, before it is ready to use as "this" in an inner class creation. In addition to earlier suggestions, you could change Parent to have a parameterless constructor and a setter for its SubParent reference:
public Parent(){
}
public void setSub(SubParent sp){
}
The Child constructor can wait until after the super call to create the SubParent:
class Child extends Parent
{
public Child()
{
setSub(new SubParent());
}
}
I read in scjp guide as following
In fact, you can't make a new object without invoking not just the
constructor of the object's actual class type, but also the
constructor of each of its superclasses!
For example
public class Person{
}
public class Employee extends Person{
public Employee(){
}
}
I don't create a Person instance but it is legal.
Please explain for me, thank for your help.
Whenever you instantiate a subclass, it'll call your superclass' constructor first.
You can find more about this here: JSL §8.8.7
Person.java
public class Person {
public Person() {
System.out.println("Super class constructor called");
}
}
Employee.java
public class Employee extends Person {
public Employee() {
System.out.println("Sub class constructor called");
}
}
If you then instantiate your Employee:
Employee e = new Employee();
Output:
Super class constructor called
Sub class constructor called
What they actually mean is
When you are creating a subclass object, i.e. its constructor is getting called, then superclass constructor gets callued internall
This is because for the default no-argument constructor there is a default super() call to the superclass constructor.
This goes on like the class hierarchy until the Object class.
In fact, if you do not write a no-argument constructor in superclass then the subclass declaration will throw compiler error.
public class Super {
public Super(int num){
}
}
public class Sub extends Super {
}
Here, class Sub will not compile giving the error Implicit super constructor Super() is undefined for default constructor because it cannot find a no-argument constructor in super class as the default no-argument constructor i.e. provided by compiler will have an implicit call to super().
Compiler provides a default no arg constructor only if there is no other constructor defined
As we have explicitly defined Super(int num), we will have to exlicitly create no-arg constructor as follows.
public Super(){
}
First, you don't have to create a parent instance (Parent) to instantiate a child class (Employee). You must have understood wrong.
Invoking the constructor of the parent class doesn't mean to create a new parent instance object (you're not calling it with new, so no new instance is created). You are creating a child instance, and for this, you need to first invoke the parent's constructor because of inheritance. Imagine for example the parent class has private fields that must be initialized in the constructor (for example private final fields). This fields cannot be accessed from the child class, but they can be initialized from the parent class constructor. You need to initialize this fields in the child instance, and the only way is calling super().
In this case Person has a default contructor which is invoked by default, no need to explicitly call it.
But in case Person has no default constructor, you need to call it explicitly. For example:
public class Person{
private final String name;
public Person(final String name) {
this.name = name;
}
}
public class Employee extends Person {
public Employee() {
}
}
This will not compile. You need to modify Employee so it calls Person constructor explicitly. For example:
public class Employee extends Person {
public Employee(final String name) {
super(name);
}
}
Superclass' nullary constructor is implicitly called.
Its because of constructor chaining:
First statement inside a any constructor by default is super();(This is a call to super class default constructor).
I don't create a Person instance but it is legal:
thats because you have a default constructor in Person class. So Employee class constructor can actually invoke super class constructor. Person()
Bottom line, the current class in which you are declaring a constructor, all the constructor upto the base class should be accessible via super(). If not, you have to explicitly make them accessible by explicitly making a call via super with proper parameters.
You have encountered one of the oddities of java.
If you don't define any constructors, the default, or "no args", constructor is implicitly defined. It's like invisible code.
If you define any constructor, args or no args, the implicit default constructor goes away.
To further compound the mystery, the first line of any subclass constructor must be to call a constructor of the super class. If you don't explicitly call one, the no-args constructor is implicitly called.
public abstract class Person {
private String name;
public Person(String name) {
this.name = name;
System.out.println("Person");
}
public String getName() {
return name;
}
abstract public String getDescription();
}
public class Student extends Person {
private String major;
public Student(String name, String major) {
super(name);
this.major = major;
}
public String getMajor() {
return major;
}
#Override
public String getDescription() {
return "student" + super.getName() + " having" + major;
}
}
public class PersonTest {
public static void main(String[] args) {
Person person = new Student("XYZ", "ABC");
System.out.println(person.getDescription());
}
}
Ques: We cannot create objects of abstract classes, then why Person Constructor has been invoked, even its an abstract class?
Because it's still a class and its constructor is invoked as a part of the object instantiation. The fact that it is abstract doesn't have anything to do with this.
Ques: We cannot create objects of
abstract classes, then why Person
Constructor has been invoked, even its
an abstract class?
If a class is declared abstract, no objects of that class can be created. That DOESNOT mean you cannot create objects of its subclasses.
You can have references(of type abstract class) refer to a subclass(non abstract) object.
Person person = new Student("XYZ",
"ABC");
And in order to construct a Student object, you need to have the "person" parts of the student initialized, thats what exactly the constructor of the abstract super class is called for.
What you can't do is to create an instance of an abstract class.
As a Student is 'partly' a Person super(...) initializes the 'Person part' of the student, it does not create a Person.
I hope you understand what I try to say
The constructor is just a method like others. And you are calling it explicitly from your child class' constructor with:
super(name);
The Person constructor is invoked from the Student class. From the Java tutorials
An abstract class is a class that is
declared abstract—it may or may not
include abstract methods. Abstract
classes cannot be instantiated, but
they can be subclassed.
An abstract class can have constructors - they cannot be invoked directly, but only as part of constructing a subclass instance, via a call to super() in the subclass constructor.
One cannot make an instance of an abstract class but subclasses can call super(name);. Even though it is a constructor, it is just another method.
The Abstract class is a part of your overall concrete class. An Abstract class is a class that is allowed to defer many parts to its concrete implementations but it must still initialize itself.
As such it has a constructor and as such the constructor with any parameters it requires to set itself up.
When you call the super(...) method from your Student class you are explicitly calling the constructor in the Person template class. The super() call must be in the first line of the Person constructor so if your person class wishes to override the defaults set up by the Person() constructor, then you have that option. But exactly one person constructor MUST be invoked when you extend a class (Abstract or concrete).
I am quite new to programming, i have a question please help me. ( this question is java question but i can't remember the syntax but what i write here is mostly it.)
A class Person speaks "i am a person"
A class Student speaks "i am a student"
Student extends from Person
Person p = new Student
then what is p speaking then?
p is just variable, it doesn't change the type of the Object that's in it.
You can think of a cup: You can put any fluid in it, but the cup won't change the type fluid.
abstract class Fluid{
public String getTemp(){
return "unknown";
}
}
class Coffee extends Fluid{
public String getTemp(){
return "hot";
}
}
class Cola extends Fluid{
public String getTemp(){
return "ice-cold"
}
}
Fluid cup = new Coffee();
System.out.println(cup.getTemp()); //It's coffe in there, so it's hot!
p is both a Student and a Person but if you call a method (like whoAreYou()), Java will first try to find it in Student and then in Person.
"I am a student"?
This is called Dynamic Binding
I think I know what you mean...
p would say he is a student, because you will override the method where the person speaks. In Java, it should look like this:
class Person
{
public void speak()
{
System.out.println("I'm a person!");
}
}
class Student extends Person
{
#Override
public void speak()
{
System.out.println("I'm a student");
}
}
"i am a student"
This is Java's polymorphism in action. The method speaks() is defined in base class Person and is overridden in the derived class Student.
In Java a base class reference can refer to a derived class object, and when a overridden method is call on such a reference, the type of the object to which the reference refers to decides the version of the method to be executed.
Even though your reference to p is declared as a Person, p is actually an instance of Student. Therefore p will "speak" whatever a student speaks.
It is legal to have refer to a Student instance as a "Person" since "Student extends from Person".
P will say student. Because Student object is casted into Person object.
Above question completely belonging to inheritance mechanism same property used by different entities.
class Person {
String identity;
Person() {
this.identity = "Person";
System.out.println("A class " + this.getClass().getName()
+ " speaks i am a " + identity);
}
}
public class Student extends Person {
public Student() {
this.identity = "Student";
System.out.println("A class " + this.getClass().getName()
+ " speaks i am a " + identity);
}
public static void main(String[] args) {
Person p = new Student();
}
}
I would guess "i am a student". This is basic polymorphism.
If the method is not static then the Student's method will be called as others mentioned. Just be careful that if the method speak is static, then the Person's method will be called. This is called hiding.
Here it is showing the concept of Polymorphism like Super class can hold the reference of child class along with that it is also showing the concept of Inheritance like Student is a Person means class Student extends Person. So here Person is a Super class and Student is a child class. As per the polymorphism Person Class (Super Class) can hold the reference of Student class (Sub-Class).
P will Speak : I am student.
But it will only have common behavior of both class. any behavior which student has but not in Person, P will not be able to access that behavior.
Person "P" is a reference here which is initialized with object of student. So when the execution of program will start, at runtime Student's class function will be called.
Here P is the Parent class Object that is holding the child class object. this is because here parent and child relationship(through inheritance ) exists because you are extending the Parent class into the Student class. Thus Parent class Object can hold the Objects of all its children class. Now P can access all the properties of its child class.
In Java when Student extends from Person you can decide what kind of behavior Student invokes from person , You can restrict student to say if it is person, You can implement it as an static then static methods are not overridden. they just shadow. If Intentionally you want instance method then you implement its specific behavior.
There is dynamic method dispatch/dynamic binding.
Person p = new Student();
p is a reference variable that type of Person which called to Student object.Student is child class and Person is parent class which extended.Two classes has methods that static or not.
Here p will speak I am a student. This is an example of dynamic binding.
This is a example of single inheritance in java.In this example,"Person" is a base class where as "Student" is a derived class.Unless anything is specified,
Person p=new Student();
object p(it seems like object of Person) will access the properties of Student class which has overriden the properties of its own base class Person.