I have two classes (say B & C) that both derive from a class (say A). Now I need to write a class (say D) that should dynamically derive either from B or C at runtime.
B, C & A are classes provided to me through libraries and the only class in my control is D class. How do I write D with respect to constraints mentioned above. Obviously B and C have come from different vendors and hence would need different methods to be overridden in D depending on which is its parent class.
I cannot write different versions of D that would subclass from B & C since the override methods would have same code under different method names.
You should define an interface I, then define concrete implementations that correspond to B and C. At runtime you can determine which implementation of I is necessary, perhaps using a factory method. Then your code need only call methods of I instead of methods of B or C.
EDIT
There seems to be some confusion about how this works. What you want is for your business logic to operate on a consistent, stable API that belongs to you. For this you create an interface which we'll call I. Now you need implementation classes for the different external classes you need to adapt to (A, B, and C). It might look something like this:
public interface I {
void doSomething();
}
public class IA implements I {
private A a;
public IA(A a) {
this.a = a;
}
public void doSomething() {
// specific to A
a.doSomethingUnique();
}
}
// similar implementation classes for B and C
Now you need to obtain an instance of I at runtime specific to your current situation. Whatever informs you about which specific class is in use at runtime can be used for this purpose. At worst, you can do this:
// in some util class
public static I getI(Object obj) {
if (obj instanceof A) {
return new IA((A) obj);
} else if (obj instanceof B) {
return new IB((B) obj);
} else if (obj instanceof C) {
return new IC((C) obj);
}
// maybe throw an exception? or return a mock I implementation?
}
Now all your business logic refers only to instances of I and calls methods defined in your interface, abstracting away the different concrete classes you have no control over.
You can do it with private inheritance.
If you have :
class A
{
public void methodA() {...}
}
class B extends A
{
public void methodB() {...}
}
class C extends A
{
public void methodC() {...}
}
D would be implemented as :
class D
{
private B b;
private C c;
private D() {}
public static D instantiateAsB()
{
D res = new D();
res.b = new B();
}
public static D instantiateAsC()
{
D res = new D();
res.c = new C();
}
public void methodA()
{
if ( b!=null )
b.methodA();
else
c.methodA();
}
public foid methodB()
{
if ( b==null )
throw new MethodNotImplementedException();
else
b.methodB();
}
public foid methodC()
{
if ( c==null )
throw new MethodNotImplementedException();
else
c.methodC();
}
}
Private inheritance has some drawbacks. One is that D would not be an A. So you can't pass a D object as a parameter to a method which requires an A. This code would not compile :
void method( A a ) {...}
D d = D.instantiateAsB();
method( d );
You can work around that using cast methods in D's definition :
// inside D class :
public A castAsA()
{
if ( b!=null )
return (A)b;
else
return (A)c;
}
public B castAsB()
{
if ( b==null )
throw new ClassCastException();
else
return b;
}
public C castAsC()
{
if ( c==null )
throw new ClassCastException();
else
return c;
}
And the previous non compiling code would be rewritten as :
D d = D.instantiateAsB()
method( d.castAsA() );
Related
I know that
class A { }
class B extends A { }
class C extends B { }
is completely legal and I can
C obj = new C();
obj.anyMethodfromA();
is possible.
Now question is this What if I don't want to access class A methods in class C only class B methods should be inherited.
Is this possible?
C anotherObj = new C();
anotherObj.anyMethodfromA(); //can be illegal?
anotherObj.anyMethodfromB(); //should be legal.
You cannot remove classA methods from classC, all you can do is override the classA method in classC and throw UnsupportedOperationException. like
class C extends B {
#override
public void someMethodWasInClassA() {
throw new UnsupportedOperationException("Meaningful message");
}
}
Restricting access for certain subclasses is not possible. You could use interfaces instead to add certain a functionality to a specific class in addition to inheritance.
You can use some sleight of hand using interface to hide the methodFromA but you cannot actually remove it.
class A {
public void methodFromA() {
System.out.println("methodFromA");
}
}
class B extends A {
public void methodFromB() {
System.out.println("methodFromB");
}
}
class C extends B {
}
interface D {
public void methodFromB();
}
class E extends B implements D {
}
public void test() {
// Your stuff.
C obj = new C();
obj.methodFromA();
// Make a D
D d = new E();
d.methodFromB();
// Not allowed.
d.methodFromA();
// Can get around it.
E e = (E) d;
e.methodFromA();
}
There is no such fine-grained inheritance in Java. Once you've marked A methods protected, that extends down the entire heirarchy.
A workaround would be to reimplement the class A methods in class C, throwing appropriate run-time exceptions. But you cannot enforce a compile time failure.
(Note that you could achieve what you want in C++ with friendships: you'd mark the methods private in class A and make class B a friend of class A.)
At the moment C is-a A, however it sounds like you don't want that. So rather than have that maybe C has-a B or B has-a A.
Prefer composition over inheritance.
Let's say I have a situation as follows:
A class X has a field s of type S.
S is extended by two classes A and B both implementing some same methods/fields that we all know should then be implemented in S but, unfortunately, this is not the case.
Now I want to do something like this:
"A or B" downcast_field;
if(s instanceof A)
downcast_field = (A)s;
else if (s instanceof B)
downcast_field = (B)s;
//do something common for the two cases but that need methods implemented both in A and B
The problem is then having in advance a static type (out of the IFs) that allows me to call such methods.
I guess that due to bad design this is actually impossible and I have to write twice the same code, which is ugly, but perhaps there is a solution that I am not seeing right now.
If you can change A and B, then you can add the same interface to both. That would allow you to give this type to downcast_field and invoke methods.
If you can't change A and B, then you have two options:
You can write A2 and B2. Copy the code from A and B into the new types. That allows you to modify the code (unless you can't control the creation of those types). Alternatively, you could also now create S2 which extends S and put the common code in there and then extend A2/B2 from that.
Create an interface and then two implementations which just delegate the calls to the real type.
In this solution, you can
Wrapper downcast_field;
if(s instanceof A)
downcast_field = new AWrapper( (A)s );
else if (s instanceof B)
downcast_field = new BWrapper( (B)s );
downcast_field.foo();
You can make the two wrappers extend the same type and move common code there.
As far as i understand your situation is the following ?
public class S {
}
public class A extends S {
public void doSomething() {
System.out.println("A is doing something ...");
}
}
public class B extends S {
public void doSomething() {
System.out.println("B is doing something ...");
}
}
actually i think this design is rather bad. if you have a chance to
clean this up you should do this. if this is not an option the following
workaround is possible ... introduce an interface declaring the common API
and wrap your instances using this interface ...
public interface WrapperInterface {
void doSomething();
}
then you might use this like so
public class Main {
public static void main(String[] args) {
WrapperInterface a=wrap(new A());
WrapperInterface b=wrap(new B());
a.doSomething();
b.doSomething();
}
private static WrapperInterface wrap(final S s) {
WrapperInterface downcast_field=null;
if (s instanceof A)
downcast_field = new WrapperInterface() {
#Override
public void doSomething() {
((A) s).doSomething();
}
};
else if (s instanceof B) {
downcast_field = new WrapperInterface() {
#Override
public void doSomething() {
((B) s).doSomething();
}
};
}
return downcast_field;
}
}
if i have group of classes let say class A,B,C and D and Class A initiate class B, class B initiate class C and class C initiate class D and their is arguments must be passed from A to D, what is the best way to passing??do i have to pass the arguments across all the classes i have ??
i tried this solution but i search for one easier.
class A
{
B b=new B(the_arguments);
}
class B
{
C c=new C(the_arguments);
}
class C
{
D d=new D(the_arguments);
}
thanks in advance .
Can you create a constructor in each successive class that takes a single argument of the previous class type? You'd need to make appropriate getters, or expose the arguments to the other classes (which wouldn't be too bad if they derived from each other).
class A
{
B b = new B(this);
}
class B
{
B(A a) { this.foo = a.foo; ... } // Constructor
C c = new C(this);
}
class C
{
C(B b) { this.foo = b.foo; ... } // Constructor
D d = new D(this);
}
class D
{
D(C c) { this.foo = c.foo; ... } // Constructor
}
class A {
public A get() { }
}
class B extends A {
}
The return types are incompatible for the inherited methods,
how to solve this problem ?
From JDK 5, Java allow you to alter the return type of an overridden method, as long as the new type is a subclass of the original one.
This is called covariant return type.
Following code will compile correctly:
class A {
A get() {
return new A();
}
void sayHello(){
System.out.println("Hello");
}
}
class B extends A {
#Override
B get() {
return new B();
}
void sayGoodbye(){
System.out.println("Goodbye");
}
}
class Test{
void check(){
B two=new B();
two.get().sayGoodbye();
}
}
Remember that the return type of the overridden method should be a subclass of the return type, to allow you to call the method on A variables and get a valid A object (which is infact a B instance):
void check(){
A two=new B();
A copy=two.get();
copy.sayHello();
}
Use generics:
class A<T extends A> {
public T get() { }
}
class B extends A<B> {
}
B b = new B();
B got = b.get();
I'm assuming you want to write something like B b = new B().get(); without explicit typecasting like Nikita Beloglazov suggests, though that's not an idiom that Java supports well. Eugene's answer works well enough, though that still involves a cast to T and generates an ugly compiler warning besides. Personally, I would write code more like the following:
class A {
private A() {}
public A get() {
return new A();
}
}
class B extends A {
private B() {}
#Override
public A get() {
return new B();
}
public B getB() {
return (B) get();
}
}
You still can't do B b = new B().get();, but you can do B b = new B().getB();, which is just as easy and a bit more self-documenting anyways, since you already know you want a B object, not just any A object. And A a = new B().get(); would create a B object, albeit one that only has access to the methods declared in A.
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.