Jonah11
asked on
When is it not bad form to cast in Java?
Say you have custom generic class MyList<Elm extends ListElm>
where ListElm is an interface. Now you have client code working with a concrete instance of MyList, instantiated using an implementor of ListElm, which also happens to have some of its own methods which are not part of the ListElm interface:
The code above won't work as is. I am required to manually cast "myList" to "ListElmClass" before calling someMethodFromListElmClass ().
1. Is it bad form to do this? If so, what is the better way?
2. Why doesn't this work? Is it something to do with erasure?
Thanks!
where ListElm is an interface. Now you have client code working with a concrete instance of MyList, instantiated using an implementor of ListElm, which also happens to have some of its own methods which are not part of the ListElm interface:
MyList<ListElmClass> myList = new MyList<ListElmClass>();
myList.someMethodFromListElmClass(); // where someMethodFromListElmClass() exists in ListElmClass but not in ListElm
The code above won't work as is. I am required to manually cast "myList" to "ListElmClass" before calling someMethodFromListElmClass
1. Is it bad form to do this? If so, what is the better way?
2. Why doesn't this work? Is it something to do with erasure?
Thanks!
this stuations is similar to the situation with say ArrayList
iif i say
ArrayList<String> ar;
then ar is an instance of ArrayList, it is not an isntance of String and I can neither
invoke methods of String on ar, say ar.substring(...) is wrong
and I would not be able to cast ar to String
ArrayList<String> ar is isntance of ArrayList, juts ArrayList has parameter and this paramtere should be some type which in this case is specified as String
it does not give me ability to think that ar is instance of string and I cannot cast ar to String
iif i say
ArrayList<String> ar;
then ar is an instance of ArrayList, it is not an isntance of String and I can neither
invoke methods of String on ar, say ar.substring(...) is wrong
and I would not be able to cast ar to String
ArrayList<String> ar is isntance of ArrayList, juts ArrayList has parameter and this paramtere should be some type which in this case is specified as String
it does not give me ability to think that ar is instance of string and I cannot cast ar to String
>implementor of ListElm, which also happens to have some of its own methods which are not part of the ListElm interface:
this implementor of ListElm is actually type parameter of MyList and therefore you cannot invoke methods of this implementor, no matter if those are methods of your interface, or some other methods, on the instance of MyList
this implementor of ListElm is actually type parameter of MyList and therefore you cannot invoke methods of this implementor, no matter if those are methods of your interface, or some other methods, on the instance of MyList
Consider this simple example showing distinction between genericised class
and its paramater type:
(see my comments in the code):
and its paramater type:
(see my comments in the code):
class MyClass<T> {
T myObject;
public MyClass(T tt){
myObject = tt;
}
public T getParamInst(){
return myObject;
}
}
class A {
public static void main(String[] args) {
MyClass<String> mc = new MyClass<String>("ttytyt");
String s2 = mc.substring(0,5); //error, as mc is not a String - compiler complains
String s = mc.getParamInst();
String s1 = s.substring(0,5); // no error, as method getParmInst() returned typ of parameter T, which happens to be string
}
}
you can't access the additional methods defined in ListElmClass in MyList and you shouldn't be doing casting there, instead what you can do is,
class ListElmClassList extends MyList<ListElmClass>{
}
here you'll be able to access additional methods defined in ListElmClass
>>MyList<ListElmClass> myList = new MyList<ListElmClass>();
this will be changed to,
ListElmClassList myList = new ListElmClassList();
class ListElmClassList extends MyList<ListElmClass>{
}
here you'll be able to access additional methods defined in ListElmClass
>>MyList<ListElmClass> myList = new MyList<ListElmClass>();
this will be changed to,
ListElmClassList myList = new ListElmClassList();
instance of class MyList<ListElmClass>
just does not have methods of ListElmClass, it is absolutely different class
the same way as instance of ArrayList<String> does not have methods of String
just does not have methods of ListElmClass, it is absolutely different class
the same way as instance of ArrayList<String> does not have methods of String
ASKER
Everyone,
I'm sorry for the confusion. My original code snippet should have read:
That is, we are trying to invoke the method on an element of the list, not on the list itself. Everything else in my OP should hopefully make more sense now.
I'm sorry for the confusion. My original code snippet should have read:
MyList<ListElmClass> myList = new MyList<ListElmClass>();
myList.get(1).someMethodFromListElmClass(); // where someMethodFromListElmClass() exists in ListElmClass but not in ListElm
That is, we are trying to invoke the method on an element of the list, not on the list itself. Everything else in my OP should hopefully make more sense now.
OK, this makes much more sense
but if you declaethat each element implements interface ListElm
then complier only knows that on this element you caninvoke methods of that interface
so if you want to invoke some other methods - you need to explicitly tell compiler that it belongs to the class which has these additional methods - to cast to that class
but if you declaethat each element implements interface ListElm
then complier only knows that on this element you caninvoke methods of that interface
so if you want to invoke some other methods - you need to explicitly tell compiler that it belongs to the class which has these additional methods - to cast to that class
this is still not clear what you mean:
> someMethodFromListElmClass () exists in ListElmClass but not in ListElm
how many classes/interfcaes do you have and how you declare them?
> someMethodFromListElmClass
how many classes/interfcaes do you have and how you declare them?
Is ListElm class or inteface?
>>myList.get(1).someMethod FromListEl mClass(); // where someMethodFromListElmClass () exists in ListElmClass but not in ListElm
>>
this should work! what error you get?
>>
this should work! what error you get?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
ListElm is an interface, but that doesn't matter. It could be a superclass of ListElmClass as well.
This is my question. Why can't the compiler tell from my declaration MyList<ListElmClass> that now this specific list is a list of ListElmClass, and not just plain ListElm?
And again, to return to my OP, is it considered poor design to do this the way I have, where casting is required?
then complier only knows that on this element you caninvoke methods of that interface
so if you want to invoke some other methods - you need to explicitly tell compiler that it belongs to the class which has these additional methods - to cast to that class
This is my question. Why can't the compiler tell from my declaration MyList<ListElmClass> that now this specific list is a list of ListElmClass, and not just plain ListElm?
And again, to return to my OP, is it considered poor design to do this the way I have, where casting is required?
check this - i just checked it with compiler - all very logical
interface ListElm {
public void method();
}
class ListElmClass implements ListElm {
public void method() {
}
public void method2() {
}
}
class MyList<T> {
T t;
public T getT() {
return t;
}
}
class B {
public B() {
MyList<ListElm> myList = new MyList<ListElm>();
myList.getT().method();
myList.getT().method2(); // this causes error - it deoes know that it has method() but does not know taht is has method2()
((ListElmClass) myList.getT()).method2(); // this is OK
}
}
can you respond to #37755949?
if you reeally declare it like that:
MyList<ListElmClass> myList = new MyList<ListElmClass>();
then there is no error - i just checked
MyList<ListElmClass> myList = new MyList<ListElmClass>();
then there is no error - i just checked
interface ListElm {
public void method();
}
class ListElmClass implements ListElm {
public void method() {
}
public void method2() {
}
}
class MyList<T> {
T t;
public T getT() {
return t;
}
}
class B {
public B() {
MyList<ListElmClass> myList = new MyList<ListElmClass>();
myList.getT().method();
myList.getT().method2(); // this is fine
((ListElmClass) myList.getT()).method2(); // this is OK
}
}
>>MyList<ListElm> myList = new MyList<ListElm>();
change it to and see,
MyList<ListElmClass> myList = new MyList<ListElmClass>();
change it to and see,
MyList<ListElmClass> myList = new MyList<ListElmClass>();
I think you have not quite correct logic
when saying this
MyList<ListElmClass> myList
you are saying that myList is an instance of class MyList<T> where parameter is type ListElmClass
Thsi by no means shoudl mean that myList is inatnce of ListElmClass and as a rule it will not be instance of ListElmClass and you will not be able to use mnethods of ListElmClass on myList and you should not be able to cast it to ListElmClass