문제

I have the following code in an abstract java class:

protected abstract <E extends HasText & IsWidget> E createNewDisplayWidget();

Which compiles fine. However if I call it anywhere, the compiler complains:

Bound mismatch: The generic method createNewDisplayWidget() of type DemoClass is not applicable for the arguments (). The inferred type HasText is not a valid substitute for the bounded parameter <E extends HasText & IsWidget>

Is there a way to require an abstract method to return something that should implement multiple interfaces?

Note: No, I cannot create a special interface that implements the two I like. GWT has widgets like Label which already implement said interfaces and I would like to use said widget.

Edit: I got the idea to do this from here (page 22):

http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

도움이 되었습니까?

해결책 2

The problem was in Eclipse. I upgraded from 3.7 to 3.7.2 and the compiler error went away.

I don't know the details of what effect this had. If someone has a clue please feel free to update my answer.

다른 팁

I have given a try on the basis of your question and i was able to get through without an error. Please check the classes that i have created.

TestClass

public abstract class TestClass {

    protected abstract <E extends HasText & IsWidget > E createNewDisplayWidget();

}

HasText class

public class HasText {

}

IsWidget

public interface IsWidget {

}

DemoClass

 public class DemoClass extends HasText implements IsWidget{

    }

TestClass1

public class TestClass1 extends TestClass{

    @Override
    protected DemoClass createNewDisplayWidget() {
        // TODO Auto-generated method stub
        DemoClass type = new DemoClass();
        return type;
    }

    public void checkOut(){
        if(createNewDisplayWidget() instanceof HasText || createNewDisplayWidget() instanceof IsWidget){
            System.out.println("Yes it works");
        }
        else{
            System.out.println("It doesnt");
        }
    }

    public static void main(String[] args){
        TestClass1 check = new TestClass1();
        check.checkOut();

    }

}

When i run my main program i always get "Yes it works". Please let me know am i missing something.

So I tried doing the complete code to generate the error, but for some reason it didn't give an error. Will look into it in a bit:

import java.util.LinkedList;

public abstract class DemoClass {

    public static void main(String[] args) {
        DemoClass dc = new DemoClassImpl();
        dc.createNewLivingAndDying().live();
        dc.killAll();
    }

    LinkedList<Dies> dying = new LinkedList<Dies>();

    public Lives createNewLivingAndDying() {
        Lives ab = newLivingAndDying(); // This is where I expected an error
        dying.add((Dies) ab);
        return ab;
    }

    public void killAll() {
        for (Dies dead : dying)
            dead.die();
    }

    protected abstract <E extends Lives & Dies> E newLivingAndDying();

}

class DemoClassImpl extends DemoClass {

    @SuppressWarnings("unchecked")
    @Override
    protected <E extends Lives & Dies> E newLivingAndDying() {
        return (E) new SomePrivateClass(); // This is what I don't understand
    }

}

interface Lives {
    public void live();
};

interface Dies { 
    public void die();
};

class SomePrivateClass implements Lives, Dies {

    @Override
    public void die() {
        System.out.println("Object Dies");
    }

    @Override
    public void live() {
        System.out.println("Object Lives");
    }
}

This code compiles and runs fine on my home computer but giver the error on my work computer.

Bound mismatch: The generic method newLivingAndDying() of type DemoClass is not applicable for the arguments (). The inferred type Lives is not a valid substitute for the bounded parameter <E extends Lives & Dies>

At this point I think it's a project setup issue but I don't know what it is. JRE 1.6 both.

What you want to do is only possible if Java supports interception type directly, then you can simply

   HasText&IsWidget createNewDisplayWidget();

any implementation must return an object that's a subtype of the type HasText&IsWidget; in another word, the returned type must be a subtype of both HasText and IsWidget

Unfortunately, Java does not support that.

The problem of your attempted solution can be understood from two angles:

1) constraints on a type variable are constraints on the caller; caller supplies the actual type argument, and it must satisfy the constraints. What you really want is constraints on the callee.

2) if a type variable only appears in the return type, but not types of method parameters, it is usually a sign of problem. In Java, due to the evil type erasure, the method body cannot know the runtime type argument, therefore it cannot return a value of proper type desired by caller, except for some trivial values like null; another classic example of trivial return value is

java.util.Collections  
    <T> Set<T> emptySet()
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top