簡體   English   中英

我可以在 Java 中使用嵌套泛型(也稱為更高種類的類型)嗎?

[英]Can I use nested generics (aka higher kinded types) in Java?

我試圖做類似的事情:


public class MyClass <A, B, C <A, B> > {
  ...
}

但是 Eclipse 突出顯示“B”,並說“意外,預期擴展”。 是什么賦予了? 不允許嵌套泛型嗎?

這是因為您尚未將C定義為本身使用 2 個類型參數鍵入的類型。
嘗試這樣的事情:

public class MyClass <A, B, C extends Map<A, B>> {
    // This compiles
}

如果您的模板參數不共享共享類層次結構,則可以使用接口。

例如:

interface IConverter<TFrom, TTo>
{
    TTo convert(TFrom from);
}

class IntToStringConverter implements IConverter<Integer, String>
{
    public String convert(Integer from)
    {
        return "This is a string: " + from.toString();
    }
}

class ConverterUser<TConverter extends IConverter<TFrom, TTo>, TFrom, TTo>
{
    public ConverterUser()
    {
    }

    private List<TConverter> _converter2;

    private TConverter _converter;

    public void replaceConverter(TConverter converter)
    {
        _converter = converter;
    }

    public TTo convert(TFrom from)
    {
        return _converter.convert(from);
    }
}

class Test
{
    public static void main(String[] args)
    {
        ConverterUser<IntToStringConverter, Integer, String> converterUser =
            new ConverterUser<IntToStringConverter, Integer, String>();

        converterUser.replaceConverter(new IntToStringConverter());

        System.out.println(converterUser.convert(328));
    }
}

這在 Java 中是不可能的。 請參閱語言定義的類型變量部分以及通用類和類型參數 我最近看到(某處)提到 Java 無法做到這一點,但 Scala 可以做到。 Scala Language Specification的 S4.4 證實了這一點。

下面的代碼編譯成功也一定程度上證實了這一點。

class MyClass [A, B, C [A, B]] {
}

在java中編譯產生了以下答案。

MyClass.java:1: > expected
class MyClass <A, B, C<A, B>> {
                      ^
MyClass.java:1: <identifier> expected
class MyClass <A, B, C<A, B>> {
                        ^
MyClass.java:1: ';' expected
class MyClass <A, B, C<A, B>> {
                           ^
MyClass.java:2: reached end of file while parsing
}
 ^
4 errors

但是,我猜想您的問題有一個更簡單的解決方案,因為這有點不尋常。

您不必像這樣聲明嵌套類型。 簡單地

class MyClass<A, B, C> {}

當您創建 MyClass 時,您可以執行類似的操作

MyClass<List<String>, Set<Date>, Map<Integer, Long>> instance;

我猜您希望 MyClass 成為具有類型參數 A、B 和 C 的泛型類。此外,您希望 C 成為具有類型參數 A 和 B 的泛型類。

這樣我就可以寫了

  1. MyClass < String , Date , Map < String , Date > >
  2. MyClass < String , Date , Hashtable < String , Date > >但不是
  3. MyClass < String , Date , ElementVsitor < Date , String > >

那我覺得你做不到。

這實際上是在 Java 中要求更高種類的類型。 Java 不直接支持這一點,但可以像這樣以某種迂回的方式進行模擬

interface H<K, T> { }

這里H編碼了一個更高種類的類型,它接受一個類型參數K ,它本身接受參數T

您可以使用它來例如實現一個通用仿函數。 請注意fmap是如何有效地從H<K<T>>H<K<R>>的函數,盡管我們不能直接以這種方式聲明它。

public interface Functor<K> {
    <T, R> Function<H<K, T>, H<K, R>> lift(Function<T, R> f);

    default <T, R> H<K, R> fmap(Function<T, R> f, H<K, T> h) {
        return lift(f).apply(h);
    }
}

另請參閱我的Github 存儲庫以獲取完整的工作示例。 進一步看看這個問題,它使這個概念更進一步。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM