2016-04-12 10 views
2

ここでは、2つの単純なクラスDadSonを作成します.SonはDadのサブクラスです。Java8:ラムダ関数のジェネリックバージョンのコンパイルエラー

public class Dad { 
} 

public class Son extends Dad { 
} 

は、その後、私は

public class Test { 
    public static void main(String[] args) { 
     Function<? extends Dad, String> fun = son -> son.toString(); 
     fun.apply(new Son()); 
} 

をテストするために、他のクラスのFunctionを作成しかし、私はfun.apply(new Son())にコンパイルエラーに出くわし、それは)目的球でcaptrueは(息子にappiledすることはできません(適用されます」と言っ) '。私は混乱しています、funDadを拡張するクラスのparamを必要とします、私はサブクラスを与えますが、まったくそうではありません。

さらに情報があります!私は

最後に、私はときに使用することができたのparam分からない「(目的球でcaptrueは(お父さん)にappiledすることはできません)を適用funためのparamとしてnew Dad()を試してみてください、だけでなく、エラーメッセージが表示されました汎用バージョンのFunction

ヘルプ~~~ ありがとうございます! (⊙o⊙)

+0

あなたは何をしようとしているか説明できますか?あなたの関数の引数が '拡張Dad'であることを知っているなら、なぜ' Function <? 'の代わりに 'Function 'を使うことができませんか? Dad、String> 'を拡張しますか? – sprinter

+0

最初は、要素名がSON1とSON2のenumを持ちます。ここではSon1とSon2の両方のトウクラスがあり、どちらもパパを拡張しています。外部からは、SON1やSON2のような列挙型の名前をparamとして取得しました。列挙型の名前でデータベースからSon1またはSon2にクエリを行い、Son1またはnick2の属性名を返します。両方の属性はStringですが、私は、現在の列挙型を判断するためにifブロックを使用したくないので、名前で列挙型を取得し、列挙型でデータベースにクエリし、列挙型から必要な属性を取得したいだけです – Tony

+0

したがって、属性< extends Dad、String>列挙型で、SON1(Son1 son1 - > son1.getName())。 SON2(Son2 son2 - > son2.getNickName())。しかし、私がそれを適用すると、私はちょうど私が示すようにコンパイラのエラーを得ました。手伝っていただけませんか? ( – Tony

答えて

2

は、次のことを考えてみましょう:

class Daughter extends Dad {} 

Function<Daughter, String> funcForDaughter = ...; 
Function<? extends Dad, String> fun = funcForDaughter; // ok 

fun.apply(new Son()); 

コンパイラはあなたがこれをやらせる場合は、あなただけDaughterを受け入れる方法にSonを渡すことができます。同じ理由でfun.apply(new Dad())に電話することも禁じられています。

Function<? extends Dad, String> funは、いずれもDadのサブタイプではfunが機能しているわけではありません。この時点では知られていないDadの特定のサブタイプでfunが機能することを意味します。

このように宣言することで、fun.applynull以外に呼び出すことは安全ではないので、コンパイラはそれをやりなくしません。

+0

ありがとうございました:)、このように 'Function'を宣言することはできません。' Function <?私は自分のコードのために他の方法について考えるべきでしょう。 – Tony

+0

@トニー:存在しない問題を解決しようとしており、ジェネリックスで問題を複雑にしています。 'Function 'を使ってください。 'Dad'のインスタンスを受け入れる関数は、' Son'が 'Dad'のサブクラス(かなり奇妙なもの)であれば、' Son'を含むサブクラスのインスタンスを既に受け付けることができます。ジェネリックスではなく基本OOPで、必要なタイプのサブクラスのインスタンスを常に渡すことができます。 – Holger

+0

@Holger:あなたの返信をありがとう、「機能楽しい」を使用すると、それは真実です。「お父さん」のサブクラスをparamとして受け入れることはできますが、私はサブクラスで関数を初期化できません。なぜジェネリックを使用したいのですか? Son1のインスタンスになると、Son2のインスタンスになると、Son1 :: getNameのようにSon1の値属性 'name'を取得したいのですが、 @ Sonder :: getNickNameのようなSon2の値属性 'nickName'を取得したい(私の次の返答を参照)。 – Tony