1

I have 3 light sources classes (X, Y and Z) that inherit from a more general light source class.

2 out of the 3 classes, have a "position" field. (X and Y)

In other method, I run through all light sources of a certain list and I check if the current light source is instance-of Z. If it's not, I would like to access the "position" field of X (or Y) without casting the current instance. But the compiler won't let me, I would like to tell it that on runtime, it would be okay to access this field.

Actually on both cases it won't let me access the field without casting, although on runtime it could not break.

Yeah I could write couple of more lines to handle this, but I ask this out of curiosity and because I like minimalist coding.

for (Light light : lights) {
    Vec vector;
    if (light instanceof DirLight) vector = light.direction;
    else vector = new Vec(intersectionPoint, light.position);
}
johni
  • 5,342
  • 6
  • 42
  • 70

3 Answers3

2

Often the need to cast is a sign of bad code design. In your case i can imagine quite some ways to write cleaner code:

1.Each implementation of Light could have a method which returns a Vector.

public abstract Vector getVector();

2.If it's not 'right' to have such a method you could implement Visitor-Pattern like this:

Light:

public abstract void visit(Visitor visitor);

New Interface:

public interface Visitor {
     public void visit(Light1 light);
     public void visit(Light2 light);
     public void visit(Light3 light);
}

Usage:

light.visit(new Visitor() { ... });
Community
  • 1
  • 1
DaniEll
  • 1,022
  • 4
  • 22
  • 31
  • I'll use the first tip. How expensive is casting on runtime? – johni Apr 11 '15 at 14:07
  • How expensive is casting? See [this question](http://stackoverflow.com/questions/2170872/does-java-casting-introduce-overhead-why) – DaniEll Apr 11 '15 at 17:59
1

Java is strongly typed. You're trying to access a member that exists on DirLight but not on Light, and that requires casting. There's no way around it.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
0

It's not true that there's no way around it. You can use reflection to get the field. However, this is generally something that should only be used for very strong reasons, not for reasons like the one you gave in your question. Of course, you should simply perform the cast on the object.

But here's how you can get any field of an object.

    // initialize o
    for (Field field : o.getClass().getDeclaredFields()) {
        Object value = field.get(o); 
        if (value != null) {
            System.out.println(field.getName() + "=" + value);
        }
    }
wvdz
  • 16,251
  • 4
  • 53
  • 90