views:

84

answers:

5

I have the following classes

         class A{
          private String name;
          private int value;

           public A(String n, int v){
           name = n;
           value = v;
           }

           public void print(){
           System.out.println(name + " " + value);
           }
          }



           class B extends A{
            public B(String n, int v){
              super(n,v);
            }
           }

When i say B b = new B("new object", 1);

it created an object of type B with name = new object and value = 1. and printed the same on calling print() method. But though it has those values in it, i cant access them through B's methods. Is it the limitation of encapsulation or inheritance.

Because the same situation is there in front of me where i need to extend a third party class and the properties in this class which are private but are needed in the extending class, and there are no setters and getters for the private members. So what do i have to do?

+1  A: 

If the variables are private, then you can't access them outside of the class where they are defined.

You could shadow those fields in A by assigning them to fields in class B's constructor. However, if the values are changed in A you will not know about those changes in class B and vice versa.

Randy Simon
Thanks but This i know, I wanted some more information on how to go about it.
GK
+3  A: 

If the variables are private, they are meant to be so - the designer of the class has decided they are not needed.

However, the designer of that class may have been wrong. That's not a good thing to assume in the first place, but if you really need them, you can call:

Field field = getClass().getSuperclass().getDeclaredField("privateFieldName");
field.setAccessible(true);
Object value = field.get(this);
Bozho
can you give the fqn of the Field class
GK
`java.lang.reflect.Field` - it can be seen from what `getDeclaredField()` returns
Bozho
A: 

If the private members are truly needed in the subclass, then your problem indicates poor design of the superclass. Classes that are inheritable (as "A" is because it has no "final" qualifier) must be carefully designed to avoid problems such as the one you've encountered. The best solution would be to rework class A to better support inheritance.

Failing that, the other answers are appropriate.

Steve Emmerson
The OP indicated that the parent class was third-party. That is, he or she had no control over its design and presumably could not modify it.
Matthew Flynn
@Matthew Flynn: I'm aware of that. This might cause them to rethink the decision on using a poorly-designed 3rd-party package, however. Also, they gave source-code for the superclass (though this might have been simply an example -- it's hard to tell from the English).
Steve Emmerson
Ok. I've no arguments with that. It is very possible that the third party class is poorly written and that it is not advisable to use it. On the other hand, there may already be dependencies on the class so that removing it would be excessively disruptive (again, because of poor design). Most systems implement the ball of mud pattern, after all.
Matthew Flynn
A: 

May be the third party class didn't provide any getters/setters by design. Reexamine your need for extending the class. Instead of extending the class can you achieve what you want by using composition instead of inheritance ? Is there a interface which the third party class implements, check if your requirements can be achieved by using the Decorator pattern.

sateesh
+1  A: 

I assume you need to extend A because there are other things that expect an A and you want to be able to substitute a subtype?

I also assume you have the source code of A, as you're showing it above?

A solution (not a great solution, because you'll run into issues in dealing with upgrades to the third party class, but possibly workable one) is:

Copy the entire source of A to a new file B.

Change the class definition and constructor to:

public class B extends A {
  private String name;
  private int value;

  public B(String n, int v){
    name = n;
    value = v;
  }

Now you have a subclass that overrides every method of the parent class (with exactly the same code).

Modify B as required.

Or, better yet, make the instance variables in B protected, and then create a third subclass C extending B, and put your changes in that:

    public class B extends A {
      protected String name;
      protected int value;

      public B(String n, int v){
        name = n;
        value = v;
      }

      ...
    }

    public class C extends B {

      public C ( String n, int v) {
        super(n, v);
      }

Now your subclass can access the parent's instance variables directly, while the grandparent's (A) are completely hidden and irrelevant. You've also kept your code separate from the third party code, meaning you'll have an easier time handling updates and upgrades from the third party.

Matthew Flynn