how i can dynamic downcast objects, with out instanceof statement?
I reading Bruce Eckel's Thinking in Java, and there using Class, and there is such a theme, but I was not approached
P.s. Sorry for my English.
public class GenericTest {
static private interface Base {
}
static private class A implements Base {
}
static private class B implements Base {
}
static private class C extends B {
}
private List<Class<? extends Base>> types;
private List<Base> objects;
public GenericTest() {
types = new ArrayList<Class<? extends Base>>();
types.add(A.class);
types.add(B.class);
types.add(C.class);
objects = new ArrayList<Base>(Arrays.asList(new A(), new B(), new C()));
for (Base base : objects) {
if (base instanceof A)
test((A) base);
else if (base instanceof C)
test((C) base);
else if (base instanceof B)
test((B) base);
for (Class<? extends Base> c : types)
if (base.getClass().equals(c))
test(c.cast(base));
}
}
private void test(A a) {
System.out.println("A");
}
private void test(B b) {
System.out.println("B");
}
private void test(C c) {
System.out.println("C");
}
private void test(Base base) {
System.out.println("Base");
}
public static void main(String[] args) {
new GenericTest();
}
}
Sometimes, the use of instanceof indicates a flaw in your design, probably by violating some basic principals of Object Oriented Programing.
In you case, I can oversee two solutions depending on what your final goal is. The first one is to encapsulate the specific behavior of test() in the classes A, B and C. It can be done by declaring a method test() in the interface Base, making it an abstract class and implementing it in the subclasses.
static private abstract class Base {
public void test() {
System.out.println("Base");
}
}
static private class A extends Base {
private void test() {
System.out.println("A");
}
}
static private class B implements Base {
private void test() {
System.out.println("B");
}
}
static private class C extends B {
private void test() {
System.out.println("C");
}
}
Notice that classes with an hierarchy level greater than 3 are not a good practice. Inheritance is the highest degree of coupling you can get between two objects. That is why we tend to prefer composition over inheritance.
The second way to improve your design is, as #SLaks mentioned, to use the Visitor Pattern. More about this pattern can be found here. Recommended reading on the subject are GOF and Refactoring to Patterns.
It's not exactly clear what you would like to do, but here is how you can achieve the same result without casting and instanceof.
Put the test method on interface Base:
static private interface Base {
public void test();
}
Then implement it:
static private class A implements Base {
public void test() {
System.out.println("A");
}
and similarly for B and C.
Then your loop should look like this:
for (Base base : objects) {
base.test();
}
This will result in calling A::test if base is an instance of A, B::test if base is instance of B etc. (The method is selected based on the runtime type of the referenced object).
Related
My code is similar to this:
class Base{
public void handleObject(A a){
//more code...
System.out.println("A");
}
}
class Sub extends Base{
public void handleObject(B b){
//more code specific to this instance and class B
System.out.println("B");
}
public void handleObject(C c){
//more code specific to this instance and class C
System.out.println("C");
}
}
Where B and C inherit from A.
I then want to call handleObject of Base from this code:
//...
Sub s = new Sub();
A[] obj = {new B(), new B(),new C(), new A()};
for(A o:obj){
s.handleObject(o);
}
//...
And I expect Sub.handleObject(B b) to be called for each object of type B, Sub.handleObject(C c) for type C, and Base.handleObject(A a) to be called for objects of type A.
The real result is it prints "A" three times.
Is it possible to make it work using java's overloading capabilities or must I type check every object myself? If not, what is the best practice to achieve the desired behavior?
This question is very similar to mine but the answers only show why his attempts did not work and did not offer a sufficient solution for me.
I have also tried making it work using Visitor Pattern, but in their example it seems like it is required for the Base class (or at least the interface) to know about Sub, which is something I prefer not to have my project.
I suggest you use polymorphism to your advantage. Instead of trying to figure out how to behave for different classes of objects, let each class provide its own behavior:
class A {
public void handleMyself() {
System.out.println("A");
}
}
class B extends A {
#Override
public void handleMyself() {
System.out.println("B");
}
}
class C extends A {
#Override
public void handleMyself() {
System.out.println("C");
}
}
class Base {
public void handleObject(A a) {
a.handleMyself();
}
}
class Sub extends Base {
public static void main(String... args) {
Sub s = new Sub();
A[] obj = {new B(), new B(), new C(), new A()};
for (A o : obj) {
s.handleObject(o);
}
}
}
So suppose I have 2 classes:
public class A
{
public void
f()
{
}
}
public class B
{
public void
f()
{
}
}
I would like to write a generic static method that could call f when passed an instance of A or B. I tried:
public class C
{
public static <T extends A & B> void
g(T t)
{
t.f();
}
public static void main(String[] args)
{
A a = new A();
g(a);
}
}
But the compiler claims A is not a valid substitute for "T extends A & B", which I assume is because T must extend BOTH A and B, which obviously A does not. I could not find a way to specify something like "T extends A OR B". Is something like this not achievable? I am a java neophyte, so any help with this would be appreciated.
You can only specify one generic type. Use interfaces instead.
An interface specifies a certain set of methods, each member of it has to have. A class can implement multiple interfaces.
In your example, I would define an interface with the method f():
public interface MyInterface {
void f();
}
Let A and B implement the interface:
public class A implements MyInterface
{
#Override
public void f() {
// ...
}
}
public class B implements MyInterface
{
#Override
public void f() {
// ...
}
}
Then you can just specify the interface as type of the argument for your method:
public static void g(MyInterface obj)
{
obj.f();
}
For more detail on interfaces, check the Java documentation: What Is an Interface?
I came across the following Java code that uses generics and inheritance. I truly do not understand what the following snippet does:
class A<B extends A<B>> {
...
}
What does this code do?
(I got this from DBMaker in MapDB)
It is almost clear and the question actually conists in two parts:
1) why B extends A?
2) why A inside B extends A<B> has generic type B?
Answers for these parts will be:
1) In particular example this class (A) is builder class (called DBMaker), so most of its methods return some type, which extends this builder's class type. This explains, why B should extend A class.
2) But, actualy, if we will hide for the second part ...extends A<B>, we will receive just class A<B>. So A has type variable of type B. That is why in ...extends A<B> A is marked as type A having type variable B.
This tells that A needs derived definitions to be able to do some work:
public abstract class A<T extends A<T>> {
protected T instance;
T getOne() {
return instance;
}
}
public class B extends A<B> {
public B() {
instance = this;
}
}
public static void test() {
B b = new B();
b.getOne();
}
This is most commonly used in interface definitions, where one wants to explicitly use instances of classes implementing an interface in return types or in arguments and not the interface itself:
public interface TimeSeries<T extends TimeSeries<T>> {
T join(T ts);
}
public class DoubleTimeSeries implements TimeSeries<DoubleTimeSeries> {
#Override
public DoubleTimeSeries join(DoubleTimeSeries ts) {
return null;
}
}
So I did some tests to figure this one out, and here is my test cases to see how one could use such a generic case:
public class A<B extends A<B>> {
int x = 10;
B test;
void printX() {
System.out.println(x);
}
void setB(B b) {
test = b;
}
void printB() {
System.out.println(test);
}
}
public class B extends A<B> {
}
public class Run {
public static void main(String[] args) {
A<B> test = new A<B>();
B myB = new B();
test.printX();
test.setB(myB);
test.printB();
myB.printB();
}
}
I hope the code might be self explanatory. If not leave a comment and I will try and explain what is going on. Look at the last line, myB.printB(), here we will get a null, because B has not yet been set for myB, but only for test. This demonstrates that we can have an infinite recursion into classes of B inside A (and inside B for that matter).
we can say:
myB.test.printB();
This will get an error (null pointer), but shows that we now have access to test in the A class from B, and we can go as deep as we want recursively with as many cases as we like. So the A class kind of functions as a wrapper of infinitely many B classes. Does this make sense?
This makes it easier when defining method return types such as this:
class A<B extends A<B>> {
public B getMe(){
return (B) this;
}
}
This tells Java compiler that you are in getMe() method returning a subclass of class A.
class C extends A<C> {
}
C c = new C();
c.getMe(); //returns C
I'm creating a abstractFactory class and I want to be able to send the concrete factory as a parameter. This way I can remove the if/else chain inside my abstract class.
My problem is I'm not sure how to typecast it back to the concrete class within my abstract class in order to call the createVehicle() method.
car = UniversalVehicleFactory.getFactory().createVehicle(CarFactory);
plane = UniversalVehicleFactory.getFactory().createVehicle(PlaneFactory);
Inside UniversalVehicleFactory I have the method createVehicle which is the method I'm having a problem with. What I'm trying to achieve is: take the parameter, determine its class and cast it to that, then call its internal createVehicle class.
public Vehicle createVehicle(AbstractFactory factory) {
// I want to take factory,
// cast it to the concrete factory, and
// call createMethod() on the factory
return factory.getInstance().createVehicle();
}
Help with this problem much appreciated!
I'll answer your question, but I'm curious why you want a universal factory to call a method of an abstract factory, if indeed you have to supply an instance of that factory as a parameter; you would be better off just invoking the creation method of the abstract factory directly.
Generics were invented for this purpose.
interface Factory< T > {
T make();
}
public class CarFactory implements Factory< Car > {
Car make() { ... }
}
public class PlaneFactory implements Factory< Plane > {
Plane make() { ... }
}
public class UniversalVehicleFactory {
public < T extends Vehicle > T make( Factory< T > factory ) {
return factory.make();
}
}
You'll notice that UniversalVehicleFactory doesn't implement Factory< T >.
I think you are trying to apply Abstract Factory pattern here. Here are my solution:
You can have interface VehicleFactory and factory classes:
interface VehicleFactory {
Vehicle createVehicle();
}
class CarFactory implements VehicleFactory {
public Vehicle createVehicle() {
return new Car();
}
}
class PlaneFactory implements VehicleFactory {
public Vehicle createVehicle() {
return new Plane();
}
}
Then if you want to centralize all the factory, you can have a UniversalVehicleFactory:
class UniversalVehicleFactory {
private Map<Class<T extends VehicleFactory>, VehicleFactory> factories;
static {
factories = new HashMap<Class<T extends VehicleFactory>, VehicleFactory>();
factories.put(CarFactory.class, new CarFactory());
factories.put(PlaneFactory.class, new PlaneFactory());
}
public static VehicleFactory getFactory(Class<T extends VehicleFactory> factoryClass) {
return factories.get(factoryClass);
}
}
Then in your code, use can use it like this:
Vehicle car = UniversalVehicleFactory.getFactory(CarFactory.class).createVehicle();
Vehicle plane = UniversalVehicleFactory.getFactory(PlaneFactory.class).createVehicle();
Here is some generalized code that might help you out:
public class A
{
public void paint(Graphics g)
{
}
}
public class B extends A
{
public static void main(String args[])
{
A a = new A();
B b = new B();
// This is the only one that won't work, because a is not an instance of b.
if(a instanceof B)
((B)a).draw(new Graphics());
if(b instanceof B)
((B)b).draw(new Graphcis());
if(a instanceof A)
((A)a).paint(new Graphics());
if(b instanceof A)
((A)b).paint(new Graphics());
}
public void draw(Graphics g)
{
}
}
instanceof is a great tool to use before typecasting to avoid errors. I hope this helped, if it was too general and you want me to apply it more to your situation let me know.
I recently fumbled into a problem with an API and an implementation where the following type of code appeared:
public abstract class A {
public A sum(A a) {
System.out.println("A.sum(A) called");
return null;
}
}
The implementation is a simple class:
public class B extends A {
public B sum(B b) {
System.out.println("B.sum(B) called");
return null;
}
}
When it comes to using it I write:
public class Main {
public static void main(String[] args) {
B b = new B();
A basa = new B();
b.sum(b);
basa.sum(b);
basa.sum(basa);
}
}
Which results in:
B.sum(B) called
A.sum(A) called
A.sum(A) called
I understand that B's sum does not override A's sum as its signature is different, but I'd like to provide an efficient implementation of sum for objects of effective type B. I think such design is quite classical and I would like to know how I should design my API and implementation so that it is efficient.
Of course I could provide sum(A a) in class B and check if b is an instanceof B before calling either sum(B b) or super, but I thought that instanceof was to be avoided for efficiency reasons. (if it is inefficient, it may be even less efficient with my abstract implementation)
instanceof can usually be avoided by using the visitor pattern. Depending on your needs, it may or may not be an overkill. It's flexible but quite verbose. In the example below I removed abstract from A to illustrate how it works with different types.
The trick is that when an object is asked to visit a visitor, the object itself chooses the correct accept method in the visitor. The "instanceof"-check is resolved through polymorphism. (I doubt that it's more efficient than an instanceof though.)
interface Visitor {
public A accept(A a);
public B accept(B b);
}
class A {
public A sum(A a) {
System.out.println("A.sum(A) called");
return null;
}
public A visit(Visitor sv) {
return sv.accept(this);
}
}
class B extends A {
public B sum(B b) {
System.out.println("B.sum(B) called");
return null;
}
public B visit(Visitor sv) {
return sv.accept(this);
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
A basa = new B();
a.visit(new SumVisitor(b)); // a.sum(b);
b.visit(new SumVisitor(b)); // b.sum(b);
basa.visit(new SumVisitor(b)); // basa.sum(b);
basa.visit(new SumVisitor(basa)); // basa.sum(basa);
}
static class SumVisitor implements Visitor {
A arg;
SumVisitor(A arg) { this.arg = arg; }
public A accept(A a) { return a.sum(arg); }
public B accept(B b) { return b.sum(arg); }
}
}
Output:
A.sum(A) called
B.sum(B) called
B.sum(B) called
B.sum(B) called
Disclamer; It was a while ago I wrote a visitor, so please correct me if I have any bugs in this (almost untested) code snippet. Or better, edit the post yourself and improve it :)
Since B instances can be summed with A instances using myA.sum(myB), you should be able to change B's definition of sum so that it does override, unless of course sum is a placeholder and isn't something that should be commutative.
UPDATE:
If this is insufficient, you could start getting fancy with generics. Here's a rough pass at what I mean:
public abstract class A {
public <T extends A> T sum(T a) {
System.out.println("A.sum(A) called");
return null;
}
public static void main(String args[]) {
B b = new B();
b.sum(b);
A basa = new B();
basa.sum(b);
basa.sum(basa);
}
public static class B extends A {
#Override
public <T extends A> T sum(T b) {
System.out.println("B.sum(B) called");
return null;
}
}
}
#aioobe is right that the generally accepted work-around is to use the Visitor pattern. I'm offering these as less complete but less verbose alternatives.
So, what makes you think instanceof is slow? It's used in several places in the JDK where they want to provide a "fast path" for certain well-known implementations of an abstract class or interface. The usual advice applies here: "Test, don't guess."