Problems with inheriting generics from Java

时间:2017-10-08 07:51:20

标签: java generics

An error was reported when the find method was called.

interface Node<N extends Node<N>> {
    void setNext(N next);
    N getNext();
}

interface Entry<K, V> extends Node<Entry<K, V>> {
    K getKey();
    void setValue(V value);
    V getValue();
}

class Test {
    public static <N extends Node<N>> N find(N base, Object obj) {
        for (N node = base; node != null; node = node.getNext())
            if (node.equals(obj))
                return node;
        return null;
    }

    public static <K, V, E extends Entry<K, V>> E getEntry(E[] table, K key) {
        return find(table[0], key);
    }
}

Bound mismatch: The generic method find(N, Object) of type Test is not applicable for the arguments (E, K). The inferred type E is not a valid substitute for the bounded parameter >

I do not know why this is so.

2 个答案:

答案 0 :(得分:4)

问题在于:

interface Node<N extends Node<N>> {
    void setNext(N next);
    N getNext();
}
interface Entry<K, V> extends Node<Entry<K, V>> {
    K getKey();
    void setValue(V value);
    V getValue();
}

你有E extends Entry<E, V>E.getNext()返回什么?由于Entry<K, V> extends Node<Entry<K, V>>E.getNext() 至少返回Entry<K, V>,这是肯定的。

但它会E吗? Entry<K, V>.getNext()仅保证返回Entry<K, V>的某个实例。但不能保证返回与Entry<K, V>实际上完全相同的类型。代码中没有任何内容强制E.getNext()返回E,只有某些实例分配兼容Entry<K, V>

因此,对find方法推断的最佳方法是Entry<K, V>E不一定与/* This program assumes that names and IDs data file (location and name) is passed as the first argument and marks data files is passed as the second argument */ #define MAXRECORDS 100 #define MAXNAMELENGTH 15 #include <stdio.h> #include <stdlib.h> #include <string.h> //Define structure to hold student data struct StudentRecord { char FirstNames[MAXNAMELENGTH]; char LastNames[MAXNAMELENGTH]; int IDNums; int Marks; }; int main(int argc, char * argv[]) { struct StudentRecord SRecords[MAXRECORDS]; int numrecords, nummarks, recordnum, r; char Temp[1]; //Read in Names and ID data FILE * NamesIDsDataFile; if((NamesIDsDataFile = fopen(argv[1], "r")) == NULL){ printf("Can't read from file %s\n", argv[1]); exit(1); } numrecords=0; while (fscanf(NamesIDsDataFile,"%s%s%d",&(SRecords[numrecords].FirstNames[0]), &(SRecords[numrecords].LastNames[0]), &(SRecords[numrecords].IDNums)) != EOF) { numrecords++; } fclose(NamesIDsDataFile); //Read in marks data FILE * MarksDataFile; if((MarksDataFile = fopen(argv[2], "r")) == NULL){ printf("Can't read from file %s\n", argv[2]); exit(1); } nummarks=0; while(fscanf(MarksDataFile,"%d",&(SRecords[nummarks].Marks)) != EOF) { nummarks++; } fclose(MarksDataFile); //Print out data as read in for(recordnum=0;recordnum<numrecords;recordnum++){ printf("%s %s %d %d\n",SRecords[recordnum].FirstNames,SRecords[recordnum].LastNames,SRecords[recordnum].IDNums, SRecords[recordnum].Marks); } printf("A total of %d records printed.\n",numrecords); while (recordnum>0){ numrecords=0; while (SRecords[numrecords].LastNames[0] != EOF ){ r= strcmp(SRecords[numrecords].LastNames, SRecords[numrecords+1].LastNames); if (r>0){ strcpy(Temp, SRecords[numrecords].LastNames); strcpy(SRecords[numrecords].LastNames, SRecords[numrecords+1].LastNames); strcpy(SRecords[numrecords+1].LastNames, Temp); } numrecords++; } recordnum--; } printf("\nTHE SORTED NAMES ARE AS FOLLOWS\n"); for(recordnum=0;recordnum<numrecords;recordnum++){ printf("%s %s %d %d\n",SRecords[recordnum].FirstNames,SRecords[recordnum].LastNames,SRecords[recordnum].IDNums, SRecords[recordnum].Marks); } printf("A total of %d records printed.\n",numrecords); return EXIT_SUCCESS; } 兼容。

答案 1 :(得分:2)

我们知道

Entry<K, V> extends Node<Entry<K, V>>

E extends Node<Entry<K, V>>

这两件事共同意味着

find

但是,为了使E extends Node<E> 方法适用,我们需要

E

但这不符合,因为Entry<K, V>只是Node的子类型,不等于它。

问题是虽然N有一个表示其自己的具体实现类型(Entry)的类型参数,但interface Entry<K, V, E extends Entry<K, V, E>> extends Node<E> { K getKey(); void setValue(V value); V getValue(); } public static <K, V, E extends Entry<K, V, E>> E getEntry(E[] table, K key) { return find(table[0], key); } 却没有。您可以通过为此目的添加第三个类型参数来修复它。

ES6