Java downcasting and is-A has-A relationship - java

HI,
I have a down casting question, I am a bit rusty in this area.
I have 2 clasess like this:
class A{ int i; String j ; //Getters and setters}
class B extends A{ String k; //getter and setter}
I have a method like this, in a Utility helper class:
public static A converts(C c){}
Where C are objects that are retireved from the database and then converted.
The problem is I want to call the above method by passing in a 'C' and getting back B.
So I tried this:
B bClasss = (B) Utility.converts(c);
So even though the above method returns A I tried to downcast it to B, but I get a runtime ClassCastException.
Is there really no way around this? DO I have to write a separate converts() method which returns a B class type?
If I declare my class B like:
class B { String k; A a;} // So instead of extending A it has-a A, getter and setters also
then I can call my existing method like this:
b.setA(Utility.converts(c) );
This way I can reuse the existing method, even though the extends relationship makes more sense. What should I do? Any help much appreciated. Thanks.

The cast from type A to type B:
B bClasss = (B) Utility.converts(c);
doesn't work because objects of type A don't have all the methods that might be called from references of type B. What would you expect to happen if you called
bClasss.getK();
on the next line? The underlying object has no member variable k, so this cast is not allowed.
You can use references of the higher types in your class hierarchy to refer to objects of lower types, but not the other way around.
Without knowing more, I think the best thing to do is implement multiple methods
A aObj = Utility.convertToA(c);
B bObj = Utility.convertToB(c);
If B extends A, then you should still benefit from some code reuse in the constructors of your classes.

What's important here is what Utility.converts() actually returns - if it doesn't create a new B object and return it, there's no way to get a B from it.
(since you're getting ClassCastException, then it doesn't create B inside)

You should work in the appropriate level of abstraction and write your method signatures to do the same. If the public/default interface of B is modified that heavily from A, then your method signature really should be returning a B. Otherwise, ditch trying to cast it, assign the result of .converts to a variable of type A, and treat it like an A even though it's true type is really a B. You would be defeating the point of abstracting through inheritance if you are trying to downcast here.
Without seeing your source code, I have no clue whether or not it makes sense to use composition in lieu of inheritance here. The above paragraph assumes what you say about "extends relationship makes more sense" is really true.

If your converts() method doesn't actually return a B, then there is no way to cast it to a B. Since you are getting a ClassCastException it clearly doesn't return a B.
You can of course write a converts(C c) that returns a B. But an alternative approach might be to write a constructor:
B(A a)
which creates a B based on the contents of A. Then you use converts to get a C, and create a B from it.

Related

Is there a point in upcasting "this" reference in Java?

I have come across a weird piece of code. I was wondering if there is any usage for it.
class C extends B {
int xB = 4;
C() {
System.out.println(this.xB);
System.out.println(super.xB);
System.out.println(((B)this).xB); // This is the weird code.
}
}
Program prints 4, 10, 10. public xB field of class B has the value 10.
In Java, you can only directly inherit from a single class. But you can have multiple indirect superclasses. Could this be used in upcasting the "this" reference to one of those? Or is this bad programming practice and i should forget about it?
So "((B)this)" basically acts as if it is "super". We could just use super instead of it.
It does NOT generally do the same thing as super.
It does in this case, because fields do not have dynamic dispatch. They are resolved by their compile-time type. And you changed that with the cast.
But super.method() and ((SuperClass)this).method() are not the same. Methods are dispatched at runtime based on the actual type of the instance. The type-cast does not affect this at all.
I was wondering if people are using this structure to upcast "this" to indirect superclasses.
They don't have to, because they don't duplicate field names like that.
It is bad practice to shadow an inherited (visible) field in a subclass (exactly because it leads to confusion like this). So don't do that, and you want have to have this cast.
And you cannot "upcast to indirect superclasses" at all where methods are concerned: You can call super.method() directly (if you are in the subclass), but not something like super.super.method().
this is an instance of C, it can be upcasted to its direct (e.g. B) or indirect (e.g Object) parent.
C c = this;
B b = (B)c;
Object o = (Object)c;
Is this bad programming practice and I should forget about it?
It's a workaround since polymorphism doesn't work for fields. It's a bad practice. Why would C need to declare xB if it's already defined in B and B can grant access to its subclasses to access and work with the field? It's weird, indeed.

Cast Object[] to another type

I have class A and class B, where class B requires only 5 of 10 properties from A.
So i have something like,
A[] objArray = populateResponse();
And to cast it into B , i do something like
for (A : objArray ){
// getters here and push it to B obj array manually
}
Any other suggestions to do it in a better way since A has many fields and size of the array can grow large ?
Thanks in advance !
If B extends or implements A, just cast away.
Otherwise - you can't do that. You will get a ClassCastException.
If the two classes are not related and you still want to do that, you should make them related. Create an interface they will both implement and pass around references to that interface. This will still not allow you to cast A to B, though.
If you're worried about too many instances of A, you can convert them to B. Write a function that takes an instance of A and creates an instance of B from it, and lose the A instance.

how to make List of of mutable objects Immuatable

Hi I was asked this interview question that you have list of objects in an immutable class, Is the class really immuatable, what can be modified and how can you prevent it. I gave the below solution.
public final class A{
final List<B> listOfB; // B is mutable
public List<B> getListOfB(){
return Collections.unmodifiableList(this.listOfB);
}
}
now he says even after getting getListOfB() he can change the 'B' instances and wanted me to avoid this also. Then i said.
public List<B> getListOfB(){
List<B> ret;
for(B b: this.listOfB){
ret.add(b.clone()); // basically make a deep copy of 'b' for return list
}
return ret;
}
The interviewer did not respond back anything saying it was right or wrong.
This solution definately works. But is there a better way of doing it, my approach is very clumsy and requires to too much additional memory.
PS: Assume B cannot be made immutable.
Assuming B is an interface or an implementation of the interface A, you could wrap each element of listOfB by using a java.net.Proxy of B or A respectively, which intercepts all modifying calls by throwing an UnsupportedOperationException instead.
More detailed, replace each item of the listOfB with a java.net.Proxy wrapped instance, implementing A. Then whenever someone fetches an item of listOfB, he will obtain the wrapped instance instead. Whenever someone calls a setter on such a wrapped item, intercept the call and throw an UnsupportedOperationException. Hope you have an idea what I mean. It's basically what Collections.unmodifiableXXX() does. If you have knowledge of all methods which may modify the state of an item of listOfB, B does not have to be an POJO. Just make sure that your wrapper replaces all modifying methods by throwing an exception.

Java interfaces and types

Let's say you have some Java code as follows:
public class Base{
public void m(int x){
// code
}
}
and then a subclass Derived, which extends Base as follows:
public class Derived extends Base{
public void m(int x){ //this is overriding
// code
}
public void m(double x){ //this is overloading
// code
}
}
and then you have some declarations as follows:
Base b = new Base();
Base d = new Derived();
Derived e = new Derived();
b.m(5); //works
d.m(6); //works
d.m(7.0); //does not compile
e.m(8.0); //works
For the one that does not compile, I understand that you are passing in a double into Base's version of the m method, but what I do not understand is... what is the point of ever having a declaration like "Base b = new Derived();" ?
It seems like a good way to run into all kinds of casting problems, and if you want to use a Derived object, why not just go for a declaration like for "e"?
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java. The way I learned it earlier this summer was, every object has one class, which corresponds to the name of the class following "new" when you instantiate an object, but an object can have as many types as it wants. For example, "e" has type Base, Derived, (and Object ;) ) but its class is Derived. Is this correct?
Also, if Derived implemented an interface called CanDoMath (while still extending Base), is it correct to say that it has type "CanDoMath" as well as Base, Derived, and Object?
I often write functions in the following form:
public Collection<MyObject> foo() {}
public void bar(Collection<MyObject> stuff){}
I could just as easily have made it ArrayList in both instances, however what happens if I later decide to make the representation a Set? The answer is I have a lot of refactoring to do since I changed my method contract. However, if I leave it as Collection I can seamlessly change from ArrayList to HashSet at will. Using the example of ArrayList it has the following types:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
There are a number of cases where confining yourself to a particular (sub)class is not desired, such as the case you have where e.m(8.0);. Suppose, for example, you have a method called move that moves an object in the coordinate graph of a program. However, at the time you write the method you may have both cartesian and radial graphs, handled by different classes.
If you rely on knowing what the sub-class is, you force yourself into a position wherein higher levels of code must know about lower levels of code, when really they just want to rely on the fact that a particular method with a particular signature exists. There are lots of good examples:
Wanting to apply a query to a database while being agnostic to how the connection is made.
Wanting to authenticate a user, without having to know ahead of time the strategy being used.
Wanting to encrypt information, without needing to rip out a bunch of code when a better encryption technique comes along.
In these situations, you simply want to ensure the object has a particular type, which guarantees that particular method signatures are available. In this way your example is contrived; you're asking why not just use a class that has a method wherein a double is the signature's parameter, instead of a class where that isn't available. (Simply put; you can't use a class that doesn't have the available method.)
There is another reason as well. Consider:
class Base {
public void Blah() {
//code
}
}
class Extended extends Base {
private int SuperSensitiveVariable;
public setSuperSensistiveVariable(int value) {
this.SuperSensistiveVariable = value;
}
public void Blah() {
//code
}
}
//elsewhere
Base b = new Extended();
Extended e = new Extended();
Note that in the b case, I do not have access to the method set() and thus can't muck up the super sensitive variable accidentally. I can only do that in the e case. This helps make sure those things are only done in the right place.
Your definition of type is good, as is your understanding of what types a particular object would have.
What is the point of having Base b = new Derived();?
The point of this is using polymorphism to change your implementation. For example, someone might do:
List<String> strings = new LinkedList<String>();
If they do some profiling and find that the most common operation on this list is inefficient for the type of list, they can swap it out for an ArrayList. In this way you get flexibility.
if you want to use a Derived object
If you need the methods on the derived object, then you would use the derived object. Have a look at the BufferedInputStream class - you use this not because of its internal implementation but because it wraps an InputStream and provides convenience methods.
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java.
It sounds like your teacher is referring to Interfaces and Classes as "types". This is a reasonable abstraction, as a class that implement an interface and extends a class can be referred to in 3 ways, i.e.
public class Foo extends AbstractFoo implements Comparable<Foo>
// Usage
Comparable<Foo> comparable = new Foo();
AbstractFoo abstractFoo = new Foo();
Foo foo = new Foo();
An example of the types being used in different contexts:
new ArrayList<Comparable>().Add(new Foo()); // Foo can be in a collection of Comparable
new ArrayList<AbstractFoo>().Add(new Foo()); // Also in an AbstractFoo collection
This is one of the classic problems on object oriented designs. When something like this happens, it usually means the design can be improved; there is almost always a somewhat elegant solution to these problems....
For example, why dont you pull the m that takes a double up into the base class?
With respect to your second question, an object can have more than one type, because Interfaces are also types, and classes can implement more than one interface.

implementing interfaces after the fact

I think, the following can't be done in Java. But I would be happy to learn how to implement something that resembles it.
Suppose we have a class C, that is already used in compiled code. (We can neither change that code nor the original definition of C).
Suppose further there is interesting code that could be re-used, if only C would implement interface I. It is, in fact, more or less trivial to derive D that is just C + the implementation of the interface methods.
Yet, it seems there is no way, once I have a C, to say: I want you to be a D, that is, a C implementing I.
(Side remark: I think the cast (D)c, where c's runtime type is C, should be allowed if D is a C and the only difference to C are added methods. This should be safe, should it not?)
How could one work around this calamity?
(I know of the factory design pattern, but this is not a solution, it seems. For, once we manage to create D's in all places where formerly were C's, somebody else finds another interface J useful and derives E extends C implements J. But E and D are incompatible, since they both add a different set of methods to C. So while we can always pass an E where a C is expected, we can't pass an E where a D is expected. Rather, now, we'd need a new class F extends C implements I,J.)
Couldn't you use a delegate class, i.e. a new class which wraps an instance of "Class C", but also implements "Interface I" ?
public class D implements I {
private C c;
public D (C _c) {
this.c = _c;
}
public void method_from_class_C() {
c.method_from_class_C();
}
// repeat ad-nauseum for all of class C's public methods
...
public void method_from_interface_I() {
// does stuff
}
// and do the same for all of interface I's methods too
}
and then, if you need to invoke a function which normally takes a parameter of type I just do this:
result = some_function(new D(c));
If all that you need to be compatible with is interfaces then no problem take a look at dynamic proxy classes, its basically how you implement interfaces at runtime in java.
if you need similar runtime compatibility with classes I suggest you take a look at cglib or javaassist opensource libraries.
If you (can) manage the ClassLoader that loads your class C then you can try to do some class-loading time shenanigans with bytecode instrumentation to make the class implement the interface.
The same can be done during build-time, of course. It might even be easier this way (as you don't need access to the ClassLoader).
(Side remark: I think the cast (D)c,
where c's runtime type is C, should be
allowed if D is a C and the only
difference to C are added methods.
This should be safe, should it not?)
Not at all. If you could make this cast, then you could compile code that attempted to call one of the "added methods" on this object, which would fail at runtime since that method does not exist in C.
I think you are imagining that the cast would detect the methods that are "missing" from C and delegate them to D automatically. I doubt that would be feasible, although I can't speak to the language design implications.
It seems to me the solution to your problem is:
Define class D, which extends C and implements I
Define a constructor D(C c) which essentially clones the state of the given C object into a new D object.
The D object can be passed to your existing code because it is a C, and it can be passed to code that wants an I because it is an I
I believe what you want is possible by using java.lang.reflect.Proxy; in fact I have done something similar for a current project. However, it's quite a bit of work, and the resulting "hybrid objects" can expose strange behaviour (because method calls on them are routed to different concrete objects, there are problems when those methods try to call each other).
I think you that can't do it because Java is strictly typed. I believe it can be done in languages like Ruby and Python with a usage of mixins.
As for Java it definitely looks like a good usage for the Adapter design pattern (it was already proposed earlier as a "wrapper" object).

Categories