inherit all getter/setter methods of a java obj - java

I have a class A with a number of setter/getter methods, and want to implement a class B which "extends A" and provides other functionality.
I cannot modify class A, and it doesn't have a clone or constructor method that that takes a class A obj as a parameter. So basically I implement class B such that
it has a constructor that takes a class A obj as a parameter and keeps a copy of this obj
when we call setter/getter methods on B, it delegates to the class A obj
other functionality...
Class A has many setter/getter methods and I feel this implementation is not clean but not sure how to fix this. Usually I can make B extend A, but in this case I have to be able to take a class A obj as a parameter for the constructor.
I'm sorry if the question is not clear enough, please let me know if you need more clarifications. Thanks.
Example:
public class A {
private int x;
public void setX(int x) { this.x = x; }
public int getX() { return this.x; }
}
public class B {
private A a;
public B(A a) { this.a = a; }
public void setX(int x) { a.setX(x); }
public int getX() { return a.getX(); }
public void foo() { ... };
public void bar() { ... };
}
Basically A has a lots of properties X/Y/Z... and has many setters/getters. If I do this then B have many dummy setters/getters which simply delegate to the same call on a. Is there a cleaner way to implement this?

I think you're trying to extend an object of class A to add functionality to it and this is creating this dilemma. You can't copy A easily with a copy constructor and so you're trying to use composition rather than inheritance, and then that's not working.
Three options:
Do what you're doing - wrap the object of type A as something owned by B and delegate - it works and it's not too bad
Subclass A with B and then use some sort of reflection based copy routine to copy all properties from the object of type A into the new object of type B - e.g. http://commons.apache.org/proper/commons-beanutils/ copyProperties function
Create a copy constructor in class B that does what you want
Example
public class A {
private int x;
public void setX(int x) { this.x = x; }
public int getX() { return this.x; }
}
public class B {
public B(A a) {
// copy all A properties from the object that we're going to extend
this.setX(a.getX());
}
.. other stuff
}
The problem you're describing is one of extending an object. Extending a class is straightforward - just subclass it, and you have the base implementation plus your new stuff. To extend an object with the above code:
A someA = new A();
// a is initialised as an A
B aWithExtraProperties = new B(someA);
// now you have a B which has the same values as the original A plus
// b's properties
// and as B subclasses A, you can use it in place of the original A
I've tried changing an object's type at runtime like this before and it doesn't feel nice. It may be better to consider why you're doing this at all and whether there are alternatives.

If class B extends class A, it will automatically inherit all its non-private non-static methods. In your code, the getter/setters in class A are declared public, so class B will inherit them.
However, for this to work, you will need to rewrite class B's signature as follows, abd remove pretty much all code you wrote in B's body :
public class B extends A {
// here, put any functionalities that B provides in addition to those inherited from A
}
This way, you can access all the getter/setters through any reference of type A or B, like this :
public static void main(String... args) {
A a = new A();
a.setName("Bob");
System.out.println(a.getName());
B b = new B();
b.setName("Joe");
System.out.println(b.getName());
// And even this, thanks to polymorphism :
A ab = new B();
ab.setName("Mike");
System.out.println(ab.getName());
}

Related

Is it possible to "adopt" a class as a child?

I'm currently writing a class, that should serve as an add-on to already existing classes. For example, let my add-on class be the following:
public class NewClass {}
Also, assume there already exist classes like:
public final class ExistingClassA {}
public final class ExistingClassB {}
...
These I am not allowed to change.
For some algorithms, I'd like to define the existing classes to be children of my NewClass, though. So instead of inherit from some class with extends, I kind of want to achieve the opposite: I want to "adopt" a class, as if the existing classes were originally defined this way:
public final class ExistingClassA extends NewClass {}
public final class ExistingClassB extends NewClass {}
...
Is this even possible in Java? And if so, is it also possible to add a class as a parent of a class, which already extends another class?
Edit:
To make my situation a bit clearer, I'll try describing what I want to achieve in more detail. E.g. assume a variable myVar, which should only be instance of specific classes. If those classes belonged to a common parent class, this wouldn't be a problem:
public final class ExistingClassA extends CommonParentClass {}
public final class ExisitingClassB extends CommonParentClass {}
public final class ExistingClassC extends CommonParentClass {}
...
/* We're inside some class now... */
CommonParentClass myVar; // May be of ExistingClassA, ExistingClassB, or ExistingClassC.
Now say, I want myVar to be only of the class ExistingClassA or ExistingClassB. Assuming I could "adopt" those two classes with my NewClass, I could also just write:
NewClass myVar; // May be of ExistingClassA, or ExistingClassB, but not ExistingClassC.
Since this seems not to be possible (from reading the comments), what approach would be the smartest to achieve the goal of just allowing myVar so be of a subset of CommonParentClass?
There's no compile-time mechanism to check whether a class extends either class A or B. If the authors of A and B did not define that they are related, they are not.
You have several options:
You could use instanceof and then cast to the specified type.
Object myObj = ...;
if (myObj instanceof Alpha) {
((Alpha) myObj).doSomething();
}
else if (myObj instanceof Bravo) {
((Bravo) myObj).doSomethingElse();
}
else {
throw new IllegalArgumentException("myObj" must be of either Alpha or Bravo");
}
Or you could make a wrapper object accepting either in the constructor:
class Either<A, B> {
A a;
B b;
boolean isA;
Either(A a) {
this.a = a;
this.isA = true;
}
Either(B b) {
this.b = b;
}
boolean isA() {
return isA;
}
A getA() {
return a;
}
B getB() {
return b;
}
}
and then call it:
Either<Alpha, Bravo> either = new Either(...);
if (either.isA()) {
either.getA().doSomething();
}
else {
either.getB().doSomethingElse();
}
But I fail to see how you want to use those two classes. Do they have a method with the same name? And why don't you just simply use two variables?

java initialize base class fields in subclass constructor

This is a very basic question about subclasses in java, I still don't get it...
Suppose I have a superclass with three fields and with only the default constructor:
public class Superclass {
public int a;
public int b;
public int c;
}
and I want to add a field x. I cannot change Superclass, so I make a subclass:
public class Subclass extends Superclass {
public int x;
public Subclass(Superclass s) {
super();
// what to do??
}
}
I now want to generate a Subclass object from an existing Superclass object:
Superclass s = new Superclass();
s.a = "a";
s.b = "b";
Subclass sc = new Subclass(s);
sc.x = "x";
such that I can still access sc.a, sc.b etc.
How can I best do this without assigning all these fields 'by hand' in the constructor of the subclass?
You have to assign a value to the variables either in the base-class constructor or in the child class.
You can declare a parameterized constructor in sub-class to assign the value to a variable in the superclass
class Subclass extends Superclass {
public int x;
public Subclass(int a,int b, int c,int x) {
super();
this.x = x;
this.a=a;
this.b=b;
this.c=c;
}
}
Or you can declare a parameterized constructor in BaseClass, and in child class, instead of calling super(), call that parametrized constructorsuper(a,b,c)
class Superclass {
public int a;
public int b;
public int c;
public Superclass(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
class Subclass extends Superclass {
public int x;
public Subclass(int a,int b, int c,int x) {
super(a,b,c);
this.x = x;
}
}
Other than copying by hand you can't.
Java is not JavaScript where objects are prototypes of other objects, instead in Java, classes subclass other classes.
I now want to generate a Subclass object from an existing Superclass
object
In fact no, you will instantiate a Subclass object by relying on the state of a Superclass object.
As you pass the SuperClass as parameter of the Subclass constructor, you just need to use fields of it to invoke the super constructor if you declare it :
public Subclass(Superclass s) {
super(s.a, s.b, s.c); // constructor may simplify
}
Or if you have a super constructor with no arg :
public Subclass(Superclass s) {
a = s.a;
b = s.b;
c = s.c;
}
Note that in Java using the private modifier for instance fields is strongly encouraged and you should access to field via public methods.
A cleaner way for your constructor would look like :
public SuperClass(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
public Subclass(Superclass s) {
super(s.getA(), s.getB(), s.getC()); // constructor may simplify
}
If you truly cannot change the superclass, then the only way you can inspect and modify the values of the member variables is by using reflection.
You should note that if getters and setters aren't exposed to subclasses (i.e. they are private) then there's a question of whether the original creator of class wanted you to ever have access to the contained variables in the first place. Would your assignments change the behaviour of the parent in an unpredictable/unsupported way?
If the SuperClass is of your own design, then you should ensure that you always use getters and setters so that you may define the proper protocol (way to interact) with your class unambiguously. This rule also applies for the visibility of class constructors. Generally speaking, every member variable of a class should be possible to initialize via a class constructor; whether that constructor is visible, or exposes all of the possible parameters to subclasses or upon allocation by external sources, is a different story.

Enforcing interface implementation in order to use another class

SITUATION: Say there is a class A and an interface B.
REQUIREMENT: If any class, say C, wants to create objects of A and use them, then that class will also have to implement interface B.Is there any way to enforce this condition?
WHY: Now a question may arise as to why I want to do such a thing. The reason is that when a class C creates objects of A and uses them, then those objects call certain methods of C. I want to declare those methods in interface B, so that C will invariably implement those methods.
Try this snippet:
public interface B {
// methods
}
public class A {
private final B b;
public A(B b) {
this.b = b;
}
...
}
public class C implements B{
// implement B's methods
public static void main(String[] arg) {
C c = new C();
A a = new A(c);
}
}
Since you say that objects of class A will call methods on C, they will have to keep reference to C somehow. Make this reference of type B and you are done.
That is
public class A {
public A(B arg) {
....
}
}
Then in C:
A a = new A(this);
That will force class C to implement interface B.

Can I make a protected member public in Java? I want to access it from a subclass

I'm new to Java and OOP,
I was using a private subclass (actually a struct) B in a class A, and everything went well until I decided to make a parent class C for subclass B. I want make public some of the protected members of class C.
For example:
public class A {
private class B extends C {
public int product;
public int x;
public int y;
public void add() {
product=x+y;
}
}
B b=new B;
b.x=1;
b.y=2;
b.multiply();
System.out.println(b.product+"="+b.x+"x"+b.y);
public class C {
protected int x;
protected int y;
public int sum;
public C(px,py) {
x=px;
y=py;
}
public void sum() {
sum=x+y;
}
}
And I get
Implicit super constructor C() is undefined for default constructor.
Must define an explicit constructor
Of course, I could remove extends C, and go back to what I had before. Or I could make a getter/setter. But I think it is understandable that an inner struct is acceptable, and it should be able to extend other classes.
The compiler message is reasonably clear - in B you've effectively got:
public B() {
super();
}
and that fails because there's no parameterless constructor in C to call. Either introduce a parameterless constructor, or provide an explicit constructor in B which calls the constructor in C with appropriate arguments.
I'm not sure it's a good idea to have all these non-private fields, mind you - nor is it a good idea for fields in B to hide fields in C. Do you really want an instance of B to have two x fields and two y fields? You realise they will be separate fields, don't you?
If you just want to effectively provide public access, you could have:
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
(and the same for y) and remove the extra fields from B. You can't change the actual accessibility of the fields in C though.
Okay, I was fuddling with my own code and found that the problem is I needed a protected default constructor for superclass C. It works now...

Validating instances of inner-classes

I have a Java class B with an inner class C. Some methods of B accept an instance of C as parameter but I only want to accept C instances created by the proper instance of B. Is there a way to do this validation at compile time?
Example
C c1 = new C();
B foo = c1.getB(); // foo was created by instance c1
C c2 = new C();
c2.method(foo); // I want a compiler error here.
My case
Have a class names Map which hold a matrix of instances of the inner class MapArea. The nice thing about this scheme is that I can validate the xPos, and yPos fields at the constructor so no invalid Areas for a given map are built. The map as a method distanceFrom(MapArea startingPos, MapArea toLocation, MapArea... otherLocations) and I was trying to avoid to validate the map area arguments again.
If this is really the behavior you want, method() should really be defined in the inner class.
In other words, instead of:
public class C {
//...
public void method(B b) {
this.x = b.y;
//...
}
//...
public class B {
//...
}
//...
}
It should be:
public class C {
//...
public class B {
//...
public void method() {
C c = this.C;
c.x = this.y;
//...
}
//...
}
//...
}
Of course, this wouldn't solve the problem if, for example, you wanted public void method(B b1, B b2, B b3), where all three instances of B are enclosed by the same instance of C.
A compile error won't work, but you can at least throw an exception:
public class C
{
public static void main (String [] args)
{
C c1 = new C();
B b = c1.getB();
c1.useB(b); //OK
C c2 = new C();
c2.useB(b); //throws IllegalArgumentException
}
public B getB() { return new B(); }
public void useB(B b) {
if(b.getC() != this)
throw new IllegalArgumentException();
//...
}
private class B
{
public C getC() { return C.this; }
//...
}
}
There's no way (AFAIK) of doing this at compile time.
At runtime you can do it by having the outer instance's factory method pass a reference to itself to the inner instance's constructor.
The inner class would need to store that reference, such that the outer class can check whether it created that instance or not:
public class C {
public class B {
private C parent;
private B(C parent) {
this.parent = parent;
}
public C getParent() {
return parent;
}
}
public B getB() {
return new B(this);
}
public void method(B b) {
assert(this == b.getParent());
}
}
Actually, as Kip's concurrent answer shows, B can access C.this to get the parent object so there's no need to store the parent reference. However the method above would be necessary if C wasn't actually an inner class.
If you make the constructor of the inner class (C) private, I believe the enclosing class (B) can still instantiate it while other classes cannot. This ensures that only B and C can instantiate C.
Edit: I've verified that with a small mockup. Make the inner class constructor private, and then only the inner class (C) or the enclosing class (B) can instantiate it.
See http://tns-www.lcs.mit.edu/manuals/java-1.1.1/guide/innerclasses/spec/innerclasses.doc6.html for more. In particular: "Access protection never prevents a class from using any member of another class, as long as one encloses the other, or they are enclosed by a third class.".
There's no compile-time way to guard against instance-specific usage. Your best bet is probably throwing an Exception when the usage in incorrect. Another option you have is to have the parent class to have a Map of instances of the inner class, and to have other classes tell the outer class to operate on the inner class not by the instance but by some other references. This will work with other classes don't need to do anything directly with the inner class.

Categories