简体   繁体   中英

Value casting when extending Generic parent

Why does subclass still need a casting to access value from his Generic parent's properties ? Any particular reason ? have a look :

    class a<U, T> {    

    public U u;   
    public T t;    
    public a(U u, T t) {
        this.u = u;
        this.t = t;            
    }

    public U getU(){
         return u;
     }   
   }


class b extends a { 
    public b(String u, Integer t) { super(u, t); }


     // Here I call b's parent method where casting occurs
    public String get(){
    return (String) getU(); // Here's the cast
    }
}

I know that the type returned by super.getU() is U , but Isn't b inherited from a which means a 's properties will be visible to its children classes!? Plus superclass' constructor had been refered by super(11111,"aString"); ? Isn't it enough to tell b 's parent that "I'm your child passing an Integer & a String " , it looks to me like there is no relation between class "a" and class "b"

*UDPATE : code typos had been fixed ,sorry it happened because i typed in hurry.

After your edit, the problem is you are using a raw type in your extends declaration.

class b extends a {

When using a raw type, for example a , all type parameters are erased. When invoking the parent class' getU() method, the return type is erased to its upper bound, from U to Object. Your subclass method has a return type of Object. Your subclass method has a return type of String , but you attempt to return an Object`. That's why the cast is necessary.

Read

What is a raw type and why shouldn't we use it?

Don't use a raw type. Parameterize your type usage and the case won't be necessary..

class b extends a<String, Integer> {

    public b(String u, Integer t) {
        super(u, t);

    }    

    public String get() {
        return getU();  
    }
}

There is no need for cast here, as you expected.

I think that your actual problem is that when you do:

B extends A<String, Integer>

... knowing that:

class A<U, T>

... then U is String and T is Integer . Thus, your method B#callGetU() should return a String , and not an Integer . ;)


Here's an example of how your B class should look like:

class B extends A<String, Integer> {

    public B(final String u, final Integer t) {  // <- Swapped Integer and String
        super("aString", 11111); // <- Swapped 11111 and "aString"
    }

    // Here I call b's parent method here where casting occurs
    public String callGetU() {   // <- U is String, not Integer
        return getU();           // <- Removed unnecessary cast
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM