I'm designing a class hierarchy and I come across the problem as my title, here is a smaller abstraction of it:
public abstract class A {
private C c;
public A(C c) {
this.c = c;
}
// ...
}
public class B extends A {
private int a;
private int b;
// ...
public B(int a, int b, ... /* and more but no object of C */) {
super(new C(this)); // <-- this is the point, got error:
// can't access `this` .
this.a = a;
this.b = b;
// ...
}
}
public class C {
private A a;
public C(A a) {
this.a = a;
}
}
In short: A needs to keep a reference to C, vice versa, but both should be done in their constructor, and after the construction of both, the fields A a and C c should not be changed so I made them private. So in this situation what's the best practice?
The following is actually not a good example, but the point is that I have a situation need to do what the above try to do.
(More context: Now let's say I change private C c; of class A into
private List<C> someCs;
that is: A is a container of C's, so during some situation those C's need to be sorted. And for some client of each C, the client needs to know what's its parent, i.e. which A it belongs to. In this situation I need references of both directions.)
this is not a valid reference for other objects until after the constructor is done. for that reason this kind of cyclic dependency (parent with reference to child and child with reference to parent) cannot be initialized in the constructor. the parent child references also cannot be final because final must be initialized in the constructor.
you could write a factory that initializes all the parents and children. then after all are initialized you can cross reference them. but this needs child.parent and parent.child to be accessible to the factory. either they are public or have a public setter. you can do some other stunts to allow the factory to set a private variable in the parents and children but i do not recommend that.
here is one suggestion for your situation: create an object which tracks the mapping between parents and children. the mapping has method getParent(this) called from child when it needs its parent. and methods getChildren(this) and getChildrenSorted(this) called from parent when it needs its children.
the mapping can be initialized once and then locked down using private and final and whatnot preventing further changes during runtime. every parent and child can then get a private and final reference to this object.
for more information:
http://www.javapractices.com/topic/TopicAction.do?Id=252 Don't pass 'this' out of a constructor
Passing "this" in java constructor
Why must a final variable be initialized before constructor completes?
How can I initialize interdependent final references?
Related
I know what extends keyword do in java, but I want to understand what java compiler do when it sees extends keyword.
class A{
//some state
//some behavior
}
class B extends A{
}
in my opinion when compiler sees extends keywords then it creates super class object to be used in subclass. and I know we can use super reference keywords in subclass constructor to refer to super class constructor.
No, there is no reference to a superclass object. When you do new B(), with your example, there is one object created, which has a combination of A and B features, not separate B and A objects with a relationship between them. (That would be prototypical inheritance, which is used in several languages, but not Java.)
super isn't a reference to a separate object. From JLS§15.11.2:
The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.
Sometimes, it seems like there must be two separate objects, such as when you shadow an instance field:
class A {
private int field;
A(int value) {
this.field = value;
}
public void sayField() {
System.out.println("(A) field == " + this.field);
}
}
class B extends A {
private int field;
B(int aValue, int bValue) {
super(aValue);
this.field = bValue;
}
#Override
public void sayField() {
super.sayField();
System.out.println("(B) field == " + this.field);
}
}
If you do this:
B b = new B(1, 2);
b.sayField();
...you get (live copy)
(A) field == 1
(B) field == 2
If there's just one object, how can it be that this.field inside A#sayField use a different field than this.field inside B#sayField? The answer is: There are two field fields in that one object. The compiler tells the code in A#sayField to use the first one, and the code in B#sayField to use the second.
I've seen answers for questions related to mine on Stack Overflow, but I am still left with some ambiguity. A parent class method has access to its own private instance variables. If a child class inherits the class, what happens when the getA() method is called on an instance of the Child class? Does it return the a from the Parent class or the a from the Child class?
class Parent {
private int a = 10;
public int getA() {
return a;
}
}
class Child extends Parent {
private int a = 22;
}
public class Test {
public static void main(String []args) throws Exception {
Child c = new Child();
System.out.println(c.getA());
}
}
As the Method getA() is inherited, if you call this Method, you'll always invoke the Parent's Method.
The current Object will be treated as a Parent and not as a Child, and the Parent's a will be returned.
Even though you have your own variable a, this variable wont override the Parent's a. They are different from each other, have different addresses and different values.
If you want getA() to return Child's a, you need to override the Method to return your new variable.
class Child extends Parent {
private int a = 22;
#Override
public int getA(){
return a;
}
}
You could also "go crazy" and do stuff like the following:
class Child extends Parent {
private int a = 22;
#Override
public int getA(){
int superA = super.getA();
return a+superA;
}
}
That way you could return the sum of Parent's and Child's a.
(Just an example)
This is a duplicate of this SO post.
The variable a in subclass Child hides the a in the parent class Parent.
Private variables are local to the class and in your code you are inheriting the properties of the parent class so you can access getA() and it will return the parent's attribute.
And you cannot access child's variable unless you have public getter method for child attribute.
Stick to basics "private member variable will only be accessed within the class by its own member functions and fields cannot be inherited" so basically when you are accessing the private variable A in parent class , the method is supposed to access its own private member rather then the private field of any child class.
Fields cannot be overridden.
In your code, an instance of child (like the one referred to by c) has two different fields, which are both called a.
You cannot access Parent's private variables inside Child, full stop. That's the entire point of private. There is nothing* you can write inside Child to make the parent's a field equal 22.
* Technically, you could with reflection. Reflection doesn't count though, since its purpose is essentially to allow you to break things, and do things that are otherwise impossible.
i know that constructors are not inherited in java and we have to implicitly or explicitly call them and private instance variables only accessible within the class's that they are declared.
assume that we have a superclass with one private instance variable and we initialize it with superclass constructor
for example
public class SuperClass
{
private int a;
public SuperClass ( int a )
{
this.a = a;
}
.
.
.
}
and our subclass is like this
public class SubClass extends SuperClass
{
public int b;
public SubClass ( int a, int b )
{
super( a );
this.b = b;
}
.
.
.
}
so here public SubClass ( int a, int b ) there is no problem even one of it's argument is private and belong to SuperClass??? if yes, how could it possible to access a private instance variable through another class???
When you call super(a);, you're not accessing the superclass from the subclass persay. You're calling the superclass's constructor, which in turn accesses it's own variable. It's completely valid, and makes logical sense.
Also, all variables and functions of the superclass are inherited by the subclass, such that the subclass is able to access the variables of the superclass. Note that you can't access it directly if it's private, but that doesn't mean that the subclass doesn't inherit the field.
Consider the following classes:
public class A {
private int a = 5;
public int getA() {
return a;
}
}
and
public class B extends A {
public int getnumber() {
return this.getA();
}
}
If I were to do this:
B x = new B();
then
System.out.println(x.a); //invalid
It would be invalid. You cannot directly access the a field inside the B object, but even if you can't see it, it still exists. We can validate that by doing this:
System.out.println(x.getnumber());
Which prints out 5.
public SubClass ( int a, int b ) {
super( a );
this.b = b;
}
int a is a new variable, different from private int a decalred in SuperClass. When you call super(a), you are passing the value inside of the parameter variable int a to the superclass's constructor. This is then stored in private int a
so here public SubClass ( int a, int b ) there is no problem even one
of it's argument is private and belong to SuperClass??? if yes, how
could it possible to access a private instance variable through
another class???
The scope of those parameters in that constructor is limited to that code block. int a, and int b are in no way related to class level variables, they just happen to be named the same.
You should probably make a public getter for the variable, but you could also simply declare the variable as "protected" (accessible to other classes in the same package, and by subclasses), or "public" - accessible by everything.
I have another question on constructors. I have a hierarchy of more than 2 layers, Say
A,
B extends A,
C extends B.
Can I get constructors from all three layers to fire when I create an instance of C? What if I want to pass super(int anArgumentForA, int anArgumentForB); Is that even possible? Seems like that's where it's going but I don't find a way to differentiate the arguments going to A vs B. Default constructor from B seems to run and I can't feed it the value it needs in order to run a different constructor because I don't know how.
You can have each layer call super(...) to set the information in each layer.
public Class A
{
public A(Object a, Object b)
{
//do any initialization needed
}
}
public Class B extends A
{
public B(Object a, Object b, Object c)
{
super(a, b); //This will call A(a, b)
//do any initialization needed
}
}
public Class C extends B
{
public C(Object a, Object b, Object c)
{
super(a, b, c); //This will call B(a, b, c)
//do any initialization needed
}
}
Keep in mind I don't think it is advisable to use these constructors to set the Objects to a variable at each level. So you don't want to have the constructors for A, B, and C each set some object Object x = a in the constructor. Only one, at most, level in the hierarchy should maintain a reference to the Objects being passed into the constructors.
In the world of Java, when you are extending another class, you only see your direct super class' constructor. The super class is supposed to proper encapsulate the super-super class constructor.
That means, in your case, B should provide a constructor that proper encapsulate A. In case B cannot determine the argument to pass to A's constructor, it is reasonable to ask for it in B's own constructor:
class A {
A (int aArg) {
// init base on aArg
}
}
class B extends A {
B (int aArg, int bArg) {
super(aArg);
// extra initialization base on bArg and aArg
}
}
class C extends B {
C() {
super(SOME_A_ARG, SOME_B_ARG);
}
}
As per Java Specification the constructors are not inherited by sub-classes.
So, as per you requirement you should keep in mind that the super class should have scope to pass objects.
When you are declaring a class by extending another class B extends A and C extends B , you should define the constructor
such a way so that you can customize that for initialization . This declaration always depends on the depth and hierarchy of the
inheritance .
class A{
A(Object firstObj, Object secondObj){
//Do you stuff for initialization
}
}
class B extends A{
//Keep in mind that this B class will be inherited by other class
B(Object firstObj,Object secondObj,Object thirdObj){
//Call super class constructor
super(firstObj,secondObj);
//Do other initialization stuff here
}
}
class C extends B{
//Keep in mind that this C class will be inherited by other class
C(Object firstObj,Object secondObj,Object thirdObj){
//Call super class constructor
super(firstObj, secondObj, thirdObj); //call constructor of B
//Do other initialization stuff here
}
}
It always depends how you parent class constructor has defined. It depends on the number of parameter passes to parent class constructor, you need to call accordingly from child class constructor.
Hope it will help you.
I have a number of classes, please allow me to introduce them and then ask my question at the end:
I have a container class which contains two objects in a composite relationship:
public class Container{
A a;
B b;
public someMethod(){
a.getC().myMethod(b);
}
}
A and B are superclasses (or Interfaces), with subtypes that can also be the type held in the composite relationship.
A contains a member of (interface) type C:
public class A{
C c;
}
public interface C{
public void myMethod(B b);
}
public class D implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
public class E implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
My problem is that I wish to modify the state of object b from a method starting in the container class, which eventually calls code down the hierarchy, to classes D and E- calling myMethod() via dynamic binding. I want to do this because I am going to use polymorphism to run the correct myMethod() (depending on whether the type of object is D or E) and I wish to do this, rather than write IF statements.
So my problem is that it seems very bad continually passing the instance of object b down the class hierarchy to myMethod, so that I can run b-specific code to modify the state of b. Is there anything else I can do to modify b from d and e (collectively known as c)?
I can get this to work using just interfaces but without using generics- but when I added generics i had problems with types and that made me start to think if my whole design was flawed?
EDIT: I could probably do this easily just by using IF statements- but I wanted an elegant solution using polymorphism of classes D and E.
First of all, if I understood your question correctly, no instance of B is being "passed down" in your code. Dynamic dispatch will simply cause the myMethod() implementation in the actual type of a to be called with an instance of B as argument.
While it may be tedious to have to write the argument explicitly every time you implement myMethod(), there's nothing wrong with it.
The alternative is to give each subclass/implementation of A an attribute of type B. In this case, however, you would have to pass your B instance down the chain of constructors to the class that actually has your B attribute.
Your code would become:
public class A{
C c;
public A(C c) {
this.c = c;
}
public interface C{
public void myMethod(B b);
}
public abstract class CC {
protected B b;
public CC(B b) {
this.b = b;
public class D extends CC implements C {
public D(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
public class E extends CC implements C {
public E(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
And then somewhere, e.g. in Container's constructor:
b = new B();
a = new A(new E(b));
You could pass the instance of B to the constructor of E. (or use a setter). That poses issues in itself, but at least it avoids having to pass B down every time you call myMethod(), which now needs no arguments.
e.g.
somewhere inside B
E myE = new E(this);
and, inside E
final B myB;
public E(B myHigherLevelThing) {
this.myB = myHigherLevelThing;
}
public void myMethod() {
myB.changeState();
}
Use the most general interface for the declarations, I'm a little confused about your full hierarchy so there may be room for improvement there...