11

これは、2つのジェネリック型(1つは戻り型用、もう1つは仮パラメーター用)を持つJavaのジェネリックメソッドとその実装方法についてです。私はそれを機能させるために写真に何かが欠けていると思います。

問題はこれです...

これは機能しています:

public enum Getter
{
    BillItemsSize {
        @Override
        public Integer get (Object entity) {
            DesiredClass ref = (DesiredClass ) entity; // "Old time" cast
            // do things...
        }
    };

    public abstract <T,K> T get (K entity);        
}

これは機能していません

public enum Getter
{
    BillItemsSize {
        @Override
        public Integer get (DesiredClass entity) { // no cast at all
            // do things
        }
    };

    public abstract <T,K> T get (K entity);        
}

Javaコンパイラは私にこれを叫びます:

<anonymous datasource.db.Getter$1> is not abstract and does not override abstract method <T,K>get(K) in Getter

まあ、それは状況です。よろしくお願いします!それが将来他の人に役立つことを願っています!。

PD:列挙型の問題ではありません。クラス階層全体で発生します。だから、列挙型を非難することを気にしないでください、私はこれを試しましたが、機能しません。

public abstract class SuperClass
{
    public abstract <T,E> T pepe (E e);
}

public class SubClass extends SuperClass
{

    @Override
    public Integer pepe(DesiredClass e) // fails... 
    {
        return null;
    }
    
}

更新しました:

ジェネリックパラメータの場合

「ジェネリックパラメーター」(タイプがジェネリックであるもの)の場合、メソッドシグネチャで暗黙的に取得されるタイプは、そのジェネリックの上限に等しいという一般的なルールステートメントを作成できます。これは、何も指定されていない場合はObject、またはそれ以上になります。上限が使用されている場合は特定のサブクラス(たとえば、TはStringを拡張します)。

ジェネリックスの場合はタイプを返します

リターンタイプが上書きされたリターンタイプのサブタイプである限り、特定のリターンタイプでジェネリックメソッドを上書きしても問題はありません。そして、そもそもリターンタイプとは?まあ、それはたまたまオブジェクトです。デフォルトでは、コンパイラは(メソッドシグネチャで)ジェネリック型をオブジェクト型として想定します。

したがって、トリックは、汎用の戻り型を持つメソッドが実際にはオブジェクトの戻り型を持っていることを知ることです。次に、いずれかのサブクラスでメソッドが上書きされ、別の型を返すことを示す戻り型を変更した場合、問題はありません。そのメソッドは別のクラスのオブジェクトを返すだけでなく、返されるオブジェクトは必然的にObjectクラスのサブクラスになり、元のサブタイプである限り、元のメソッドとは異なる戻りタイプでメソッドを上書きしても問題はありません。 。共変リターン型と呼ばれる手法により、そのようなことが可能になります。

public abstract class SuperClass
{
    public abstract <T> T operation ();
}


public class SubClass extends SuperClass
{

    @Override
    public Chair operation()
    {
        //bla bla 
    }
    
}   

その間、コードの別の部分で...

void main ()
{
        SubClass sb = new SubClass();
        Chair chair = sb.operation ();
        // the chair type can be easely replaced by super type (like Object)
        Object object = sb.operation();
}

これをクリアするのを手伝ってくれたすべての人々に感謝します!。

4

2 に答える 2

14
public abstract <T,K> T get (K entity);        

は引数として何でも取ることができるメソッドであり、何でも返すことができます。

でオーバーライド

public Integer get (DesiredClass entity)

メソッドに渡すことができる引数のタイプをDesiredClassに制限し、Liskovの原則を破るため、は機能しません。

ジェネリックがなければ理解しやすいでしょう。クラスBarに抽象メソッドがあるとします。

public abstract void fillRecipient(Recipient r);

そして、SubBarでそれをオーバーライドしようとします

public void fillRecipient(Glass glass) {
}

上記が合法である場合、次のコードは何をしますか?

Bar bar = new SubBar();
bar.fillRecipient(new Mug());
于 2012-12-22T22:53:19.830 に答える
4

JB Nizetの回答を完成させるために、次のように記述します。

<K>

これは暗黙的に次のことを意味します。

<K extends Object>

そのメソッドはすべてのオブジェクトを受け入れる必要があります。サブクラスに限定するとDesiredClass、エラーメッセージに示されているように、事実上何も上書きされません。

オーバーライドされたメソッドは、まったく同じシグニチャを持っている必要があります。パラメータにもリターンタイプにもサブ/スーパータイプは許可されていません。

編集:実際にはコメントで説明されているように、String public foo();効果的にオーバーライドしますObject public foo();

于 2012-12-22T23:03:00.890 に答える