使用Java中的通用接口作为方法参数

huangapple go评论72阅读模式
英文:

Use generic interface as method argument in Java

问题

让我们假设我有以下接口 Foo

abstract public interface Foo {

    abstract String getFoo();
}

还有两个扩展 Foo 的类,Bar1Bar2

public class Bar1 extends Foo{

    String foo = "foobar";
    public String getFoo(){
        return foo;
    }
}
//对于类 Bar2 也类似

我想创建一个翻译器类,其中有一个客户端可以调用的方法,该方法以扩展 Foo 的任何对象为参数(如 Bar1Bar2),并将字符串翻译为其他字符串。我进行了一些探索,感觉泛型可能是实现这一目标的最佳方法,然而我无法正确地修改方法签名或类签名(不确定是哪个,也许是两者都需要修改?)以实现这种行为。

public class TranslateBar{
    
    //我尝试了以下方法签名,但显然我遗漏了一些东西    

    public String translateBar(Foo<? extends Foo> pojo){
        //返回翻译后的字符串
    }
    
    /*
    我读到 Object 是所有 Java 类的超类型,所以我想也许将其作为参数,然后使用通配符会起作用,但没有成功
    */

    public String translateBar(Object<? extends Foo> pojo){
        //返回翻译后的字符串
    }
}

在所有情况下,它都会给我一个泛型错误,指出 Type 'java.lang.Object'(或 Foo)does not have type parameters。它给我修复的两个选项是 create a field for pojo,但仍然不能解决 <? extends Points2> 错误。

如何使我的 translateBar 方法允许客户端传递 Foo 的任何子类?

英文:

Lets say I have the following interface Foo

abstract public interface Foo {

    abstract String getFoo();
}

and two classes that extend Foo, Bar1 and Bar2

public class Bar1 extends Foo{

    String foo = &quot;foobar&quot;;
    public String getFoo(){
        return foo;
    }
}
//repeat for class Bar2 

I want to create a translator class that had a method that a client can call, which takes any object thats extending Foo as an argument (like Bar1 or Bar2 and translate the string to some other string. I did some digging and feel like generics are going to be the best way to do so, however I'm unable to properly modify either the method signature or the class signatures (not sure which, perhaps both?) to allow for this behavior.

public class TranslateBar{
    
//I have tried the following signatures, but clearly I&#39;m missing something    

    public String translateBar(Foo&lt;? extends Foo&gt; pojo&gt;{
        //return translated string
    }
    
    /*
    I read that Object is the supertype for all Java classes, so I thought maybe having it 
    take an Object in the parameters and then doing the wildcard would work, but no luck
    */

    public String translateBar(Object&lt;? extends Foo&gt; pojo&gt;{
        //return translated string
    }

In all cases, it gives me an error in the generic saying Type &#39;java.lang.Object&#39;(or Foo) does not have type parameters. The two options it gives me to fix are create a field for pojo which still doesn't solve the &lt;? extends Points2&gt; error.

How can I get my translateBar method to allow the client to pass any subclass of Foo?

答案1

得分: 3

在Java中,一个接受特定类型(比如Foo)的方法也将接受任何Foo的子类型。在这种情况下,不需要使用泛型。

以下是您的代码应该如何编写:

public interface Foo {
    String getFoo();
}

public class Bar1 implements Foo {
    final String foo = "foobar";
    @Override
    public String getFoo(){
        return foo;
    }
}

public class TranslateBar {
    public String translateBar(Foo pojo) {
        //返回翻译后的字符串
    }
}

现在,您可以使用任何Foo的实现,包括Bar1,来调用translateBar方法:

new TranslateBar().translateBar(new Bar1());

对于不同的情况,您可以使用泛型。例如,在getFoo方法返回的类型取决于实现的情况下:

// 泛型类型T取决于实现
public interface Foo<T> {
    T getFoo();
}

public class Bar1 implements Foo<String> {
    final String foo = "foobar";
    @Override
    public String getFoo(){
        return foo;
    }
}

public class TranslateBar {
    public String translateBar(Foo<?> pojo) {
        //返回翻译后的字符串
    }
}
英文:

In Java, a method that accepts a certain type, say Foo, will accept also any sub-type of Foo. There's no need to use generics in such case.

Here's how your code should look like:

public interface Foo {
    String getFoo();
}

public class Bar1 implements Foo {
    final String foo = &quot;foobar&quot;;
    @Override
    public String getFoo(){
        return foo;
    }
}

public class TranslateBar {
    public String translateBar(Foo pojo) {
        //return translated string
    }
}

Now you can call translateBar with any implementation of Foo including Bar1:

new TranslateBar().translateBar(new Bar1());

You would use generic for different cases... for example, where the type returned by the getFoo method depended on the implementation.

// the type T is generic and depends on the implementation
public interface Foo&lt;T&gt; {
    T getFoo();
}

public class Bar1 implements Foo&lt;String&gt; {
    final String foo = &quot;foobar&quot;;
    @Override
    public String getFoo(){
        return foo;
    }
}

public class TranslateBar {
    public String translateBar(Foo&lt;?&gt; pojo) {
        //return translated string
    }
}

答案2

得分: 2

在您的情况下,您不需要使用泛型,基本的多态性将足够。

 public String translateBar(Foo pojo){
    //返回翻译后的字符串
}

如果您只想调用getFoo(),这将解决该问题。

英文:

In your case, you don't need to use generics as the basic polymorphism will be sufficient

 public String translateBar(Foo pojo){
    //return translated string
}

And this will solve the issue if you just want to call the getFoo()

huangapple
  • 本文由 发表于 2020年8月15日 03:46:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/63419194.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定