Passing superclass object as parameter to subclass constructor (java) - java

I've done a bit of searching, but I'm either not asking the right question or not remembering correctly. In any case, in Java, I am wondering if it is possible to pass the super class object in as a parameter to a subclass and what the most efficient way of making that object's data available to the class's super class.
Code examples:
public class superclass {
String myparm1;
String myParm2;
int myParmN;
public superclass(String p1, String p2, int pn)
{
this.myparm1 = p1;
this.myparm2 = p2;
this.myParmN = pn;
}
// other methods here
}
public class subclass extends superclass {
double b1;
double b2;
public subclass(superclass sc, double b1, double b2) {
// easy way to make sc data available to this class?
// Do I create a copy or clone method, or some other way?
// calling super(sc); wouldn't exactly work
this.b1 = b1;
this.b2 = b2;
}
}
if I had a constructor in superclass that was public superclass(superclass sc) { // assign sc properties to this properties, correct? } then I could simply use super(sc);

There's no point to passing in a reference to the superclass of an object in the constructor. Your subclass is already an instance of the superclass.
Even though you can't directly see the private components of the superclass, but they still exist and calls to public accessor methods will still produce normal behavior.
In answer to your second question, the most efficient way to access the data inside the parent class is with the accessor methods of that parent class. If it has get/set properties methods that populate some data structure full of properties, just call those methods from your child class and they'll work exactly the same as they did for the parent. Now, if those internal data structures are populated by the constructor of the parent class, you'll have to invoke that constructor with the correct methods when you create an instance of the child constructor that needs them- typically by calling the appropriate super() at the beginning of the child's constructor.
If you're trying to get around the restriction that you can't see the private parts of the superclass, java intentionally doesn't let you do that. You can get around this with reflection unless you're stuck inside an execution environment that disallows this, but I generally wouldn't consider this a safe or elegant approach.
From comment below, I understand what the OP is trying to do and this should work, though obviously it depends upon your ability to make changes to the super class:
public class Super
{
public Super (Super other)
{
//copy stuff from other to this
}
}
public class Child extends Super
{
public Child (Super other)
{
super(other);
//continue constructor
}
}

You can't. When you build an object with Java (for example with new), that instance has a class, and that class has a parent (possibly Object).
The parent-child relation only holds between classes, not between objects! No object has a parent object (at least, not at the language level) - so you can't accept the parent in the contructor and store it in some Java-defined place.
However your domain can have parent and child entities, in which case you need fields or data structures to store the links between them.

To answer a previous question, suppose the superclass has large number of properties. In that case, the design of the class may be bad, of course.
Perhaps the best answer is:
public class superclass {
// properties and constructors as defined in OP
public void copy(superclass sc) {
this.myParm1 = sc.getMyParm1();
this.myParm2 = sc.getMyParm2();
this.myParmN = sc.getMyParmN();
}
// other methods as needed
}
That way, the sub class can just call the super.copy(sc). Of course, I would need another constructor in superclass that will set defaults: public superclass() { // set defaults }
So subclass could be:
public class subclass extends superclass {
//properties as defined in OP
public subclass(superclass sc, double b1, double b2) {
this.b1 = b1;
this.b2 = b2;
super.copy(sc);
}
}
In this way, I'm only having to type those parameters out, and any subclasses that would want to accept a superclass object won't have to define that structure each and every time. (less typing, less chance for mistake or forgetting something.)

Related

Calling a method and a variable of a subclass extended from a superclass [duplicate]

This is probably answered somewhere, but I have no idea what to search for. Imagine you have the following...
The superclass, Animal.java
public class Animal {
public String noise = "squeak";
public String toString() { return noise; }
}
The subclass, Lion.java
public class Lion extends Animal {
public String noise = "ROAR!!";
public String toString() { return noise; }
}
The main class, Runner.java
public class Runner {
public static void main(String[] args) {
Animal a = new Animal();
System.out.println(a);
System.out.println(a.noise);
Lion b = new Lion();
System.out.println(b);
System.out.println(b.noise);
Animal c = new Lion();
System.out.println(c);
System.out.println(c.noise);
}
}
The output is:
squeak
squeak
ROAR!!
ROAR!!
ROAR!!
squeak
Why does c.noise return squeak? What is the difference between instance method invocation and instance variables that one returns what you'd expect, and the other does not? Why does Java do this?
Thanks
Short answer:
You can override methods, but it's not possible to override fields.
Long answer:
Each class sees the methods and fields of it's own and of it's parents (except for private methods). If the child delcares a method, whose name is the same, as the name of the method in his parent class, this method becomes overridden - if this method is somehow invoked on the child instance (even from the one of the parent's methods), the brand new method will be used instead of the parent's one. Child may still call the original method of his last parent via super.method(...) call.
But the story is different when we come to the fields. If the child declares a new field, that is named exactly as the field in parent class, it will simply hide the parent's field without overriding, just like the local variable hides global one. So the child methods will simply see the child's fields, but the parent's method will continue to see parent's field, and child's field will not be visible by any means from the parent class - that's what you've got.
Child can access the field of it's parent via ((Parent)this).field.
Longer answer:
So really the way you'd do this is define Lion thus:
public class Lion extends Animal {
public Lion() {
noise = "ROAR!!";
}
}
So now for Lion instances the noise member variable of Animal has been updated to ROAR!!
Of course you'd (almost) never actually have a public mutable member on a class like that in the wild.
You can not override fields, new declaration of noise in Lion hides parent's noise attribute. do like this:
public class Lion extends Animal {
// public String noise = "ROAR!!"; // <---- Remove this line
public Lion() {
noise = "ROAR";
}
public String toString() {
return noise;
}
}
All non-static methods in java are by default "virtual functions". Unless they're marked as final (which makes the method not overridable). Java uses a virtual method table to call the correct object's method.
This is because Java talks only about method overriding. Member variables can only be shadowed in child class. So when you say c.noise it actually refers to the string variable in parent class as the c if reference type Animal.
The topics you are interested in are Dynamic Dispatch and Virtual Method Table. Basically, by design, Java allows for methods to be overridden (assuming they are non-final) and at run time the JVM will execute the appropriate implementation. This polymorphic attribute is only afforded to methods. Good OO design would dictate the fields be encapsulated anyway.

does inheritance violates the basic law of oops..?

let me first explain what i want to say actually
Suppose a class Sub inheriting the class Super.
now we can excess all no private members of class Super within class Sub. now Suppose the case
class Super{
private int id;
public int getId()
{
return id;
}
}
class Sub extends Super {
public static void main(String args[]){
Sub sub = new Sub();
System.out.println(sub.getId());
}
}
I know that creating Sub class object will call Super class constructor too.
But the job of constructor is to initialize the fields only -- not to allocate the memory to the object.
Moreover in case of abstract class where the initialization is not allowed we can still use the instance variable of abstract class.
The memory to instance variable will be assigned at time of instance creation only.
Than how can we use the instance fields without even creating the instance.
Doesn't it violets the oops concept..??
Please help over this. And thanks in advance.
I think you're confused about what happens when you use the extends keyword. What that keyword means is that a Sub is a more-specific kind of Super. By the Liskov Substitution Principle, all of the properties of Super must hold for Sub as well. That means that all of Super's private members (methods and properties) are present in an instance of Sub. It's just that for organizational reasons, the developer of Super decided that they didn't want any derived classes messing around with it directly.
Now, how does this relate to memory allocation? In the case of Java, you are correct that the constructor does not allocate memory. It just initializes the fields. The memory allocation is handled by the runtime, and it allocates enough for the whole picture. Remember, a Sub is a Super and then some. So it allocates enough memory to hold everything from the entire inheritance chain all the way back up through java.lang.Object.
abstract classes can, in fact be initialized, or even force their derived classes to initialize their members. For example:
public abstract class Super {
private int id;
public Super(int id) {
this.id = id;
}
public int getId() { return this.id; }
}
public class Sub extends Super {
public Sub() {
super(5); // failure to call this constructor is a compiler error
}
}
Now, because Sub can't see Super's private id field, it's free to declare a new one of its own. This does not override Super's field. Any of Super's methods that use that field will still use the one from Super. This could be a little confusing, so the best advice is don't think of it that way. Generally, you'll want to override methods not fields.
I totally agree with the answer of Ian. Totally. Regarding the title of your question,
Does inheritance violates the basic law of oops..?
the answer is it depends. There is a kind of inheritance that violates encapsulation principle: implementation inheritance.
You're using implementation inheritance every time you inherit (through extends primitive) from a class that is not marked as abstract. In that case, to know how to implement your subclass, you need to know the implementation (a.k.a. the code) of methods of the base class. When you override a method, you have to know exactly which is the behavior of that method in the base class. This kind of code reuse is often referred to as white-box reuse.
Quoting the GoF's book, Design Pattern:
Parent classes often define at least part of their subclasses' physical representation. Because inheritance exposes a subclass to details of its parent's implementation, it's often said that "inheritance breaks encapsulation".
So, to reduce implementation dependencies, you have to follow one of the principles of reusable object-oriented design, which is:
Program to an interface, not an implementation
inheritance only concern about what and how is accomplished, not what is promised. If you violate the promises of the base class, what will happen? is there any guarantee that makes you sure it's compatible? -even your compiler will not understand this mistake and you will face a bug in your codes. Such as:
class DoubleEndedQueue {
void insertFront(Node node){
// ...
// insert node infornt of queue
}
void insertEnd(Node node){
// ...
// insert a node at the end of queue
}
void deleteFront(Node node){
// ...
// delete the node infront of queue
}
void deleteEnd(Node node){
// ...
// delete the node at the end of queue
}
}
class Stack extends DoubleEndedQueue {
// ...
}
if the class wants to use inheritance with aim of code reuse, It may inherit a behavior that violates its principal, such as insertFront. Let's also see another code example:
public class DataHashSet extends HashSet {
private int addCount = 0;
public function DataHashSet(Collection collection) {
super(collection);
}
public function DataHashSet(int initCapacity, float loadFactor) {
super(initCapacity, loadFactor);
}
public boolean function add(Object object) {
addCount++;
return super.add(object);
}
public boolean function addAll(Collection collection) {
addCount += collection.size();
return super.addAll(collection);
}
public int function getAddCount(Object object) {
return addCount;
}
}
I just reimplement HashSet with DataHashSet class in order to keep track of inserts. In fact, DataHashSet inherit and is a subtype of HashSet. we can instead of HashSet just pass DataHashSet(in java is possible). Also, I do override some of the methods of the base class. Is this legitimate from Liskov substitution principle? As I do not make any changes in the behavior of base class just add a track to insert actions, It seems perfectly legitimate. But, I will argue this is obviously a risky inheritance and a buggy code. First, we should see what exactly add method do. add one unit to related property and call parent class method. There is a problem with that called yo-yo. Look at addAll method, first, it adds collection size to related property then call addAll in the parent, but what exactly parent addAll do? It will call add method several times(loop over the collection), which add will be called? the add in the current class, so, the size of count will be added twice. once when you call addAll and second when parent class will call add method in the child class, that's why we call it yo-yo problem. And another example, imagine:
class A {
void foo(){
...
this.bar();
...
}
void bar(){
...
}
}
class B extends A {
//override bar
void bar(){
...
}
}
class C {
void bazz(){
B b = new B();
// which bar would be called?
B.foo();
}
}
As you see in bazz method which bar will be called? the second one the bar in class B will be called. but, what is the problem here? the problem is foo method in class A will not know anything about the override of bar method in class B, Then your invariants may be violated. because foo may expect the only behavior of bar method that is in own class, not something is overridden. This problem is called fragile base-class problem.

Difference when overridden variable and method from child class are accessed

As per my understanding, when we up cast the child object to the reference of parent class, the child object loses it specific properties pertaining to child class. However, it still recognizes overridden methods and variables.
My question is why the output shows the result from child class in case of over ridden method and result from parent class in case of overridden variables. Why is such difference in behavior among methods and variables
class A
{
int a = 2;
public void show()
{
System.out.println("Inside A");
}
}
class B extends A
{
int a = 555;
void show()
{
System.out.println("Inside B");
}
}
class Demo
{
public static void main(String[] args)
{
A obj = new B();
System.out.println(obj.a); // prints 2.
obj.show(); // prints Inside B
}
}
Because your understanding is wrong. Java objects behave pretty much like real objects. Just because you refer to a Child as a Human doesn't change anything to how the child moves, cries and plays. It's still a Child.
That's the whole point of polymorphism: you can refer to an object without knowing its concrete type, and it will behave as defined in its concrete type definition.
Note that polyporphism and overriding only applies to methods, and not fields. Fields are never resolved in a polymorphic way. They should not be accessed directly from the outside anyway: always through methods. That's the other main principle of OO: encapsulation.
In B, you're not overriding the field a, but introducing another field with the same name, which hides the one defined in A.
Overriding applies to methods, not fields. Having same field in subclass hides the super class field.
Since type of obj is A, the actual value a which is intialized in A gets printed

Don't inherit private member if it's accessed by public member

I'm sorry if this question may be asked all the time, but I searched and couldn't find an sufficient answer.
How to disable inheritance of private members/fields if they are being accessed by a public member/method?
So consider this:
public class A {
private MemberA a = new MemberA();
public void foo(TypeA x) {
a.methodCall(); //access to a
}
}
public class B extends A {
private MemberB b = new MemberB();
public void foo(TypeB x) {
b.methodCall();
}
}
If you hit the debugger you'll see, that B has a field a by type MemberA. That's in compliance with Java rules because if a public member has access to a private member it will be inherited.
But in B "a" is useless and only taking memory - even if you don't instanciate it in the constructor of B, because B calls it's super constructor and it has to be instanciated in A because a has very much use for a.
I need to have same method names for A and B and they have to be public, but since they do fundamentally different things but also share common logic B needs to be inherited from A.
So basically, I need to know how to overload and override a method the same time. Or duplicate code. What to do?
This situation -- where a class has data members that you do not want to inherit -- is called the "Refused Bequest" antipattern, and what it generally means is that your inheritance relationship is wrong. Rather than having B extend A, you need an interface C that both implement independently. If there is significant implementation that you do want to share, then perhaps you could introduce an abstract base class that A and B could share.
Alternatively, it could also be that MemberA and MemberB (not A and B) share the common interface (or abstract class), say "Member", including methodCall(). You could then do
public class A {
protected Member myMember; // sounds like an Austin Powers movie...
// in the constructor
myMember= new A();
}
while, in class B, the constructor does this instead: (or use DI, etc...)
myMember = new B();
and in foo(), which need not be overloaded, you call myMember.methodCall().
Without knowing your problem it's hard to say if this approach or #Ernest's is better. In either case you are looking for common functionality, and it will likely be the same amount of work.

Using this and super in Java

I have the following code snippet that attempts to use this and super.
class SuperClass
{
public final int x=10;
public final String s="super";
public String notOverridden()
{
return "Inside super";
}
public String overrriden()
{
return "Inside super";
}
}
final class SubClass extends SuperClass
{
private final int y=15;
private final String s="sub"; //Shadowed member.
#Override
public String overrriden()
{
return "Inside sub";
}
public void test()
{
System.out.println(super.notOverridden());
System.out.println(this.notOverridden());
System.out.println(this.overrriden());
System.out.println(super.overrriden());
System.out.println(this.s);
System.out.println(super.s);
System.out.println(this.x);
System.out.println(super.x);
System.out.println(this.y);
}
}
public final class Test
{
public static void main(String[] args)
{
SubClass subClass=new SubClass();
subClass.test();
}
}
In this simplest of Java code, the statements that redirect the output to the console inside the method test() within the class SubClass display the following output.
Inside super
Inside super
Inside sub
Inside super
sub
super
10
10
15
So, it appears that there is no difference between this and super, when they are used to access methods which are not overridden in its subclass(es) and in case of variables, when they are not shadowed in its subclass(es).
Both of them tend to point to super class members. There is however, an obvious difference, if such is not a case.
Are they same, when methods are not overridden or variables are not shadowed in respective subclasses?
So, it appears that there is no difference between this and super,
when they are used to access methods which are not overridden in
its subclass(es) and in case of variables, when they are not
shadowed in its subclass(es).
There is a difference. If you override methods in third class, and call test from it, you will see, that super still calls implementations of SuperClass. And this will call new implementations (overridden).
Addition:
this.method() usage implies the method belongs to instance of the object. So the last implementation will be used (with exception of private methods).
super.method() usage implies method of the instance, but implemented before the current class (super, or super.super etc).
Yes, they are the same. notOverridden methods and not shadowed variables are inherited by subclass.
To better understand this, knowing how object is located in memory is helpful. For example in the figure below. Assume it's an object of a subclass. The blue area is what it inherits from its parent, and the yellow area is what is defined by itself. The method has the similar design except that it uses a Vtable.
Child object has the same memory layout as parent objects, except that it needs more space to place the newly added fields. The benefit of this layout is that a pointer of parent type pointing at a subclass object still sees the parent object at the beginning.

Categories