2017-06-28 12 views
2

私がやろうとしていること:実装を使用して呼び出されるインタフェースを使用してコールバックパラメータを定義

私はいくつかのタイプを定義しています。コード全体には、コールバックがあり、コールバック型をどこにでも書く代わりに、その型を定義しました。

type Foo interface { 
    Bar() 
} 

type MyCallback func(f Foo) 

type CoolFoo int 

type BadFoo int 

func (cf *CoolFoo) Bar(cb MyCallback) { 
} 

func (bf *BadFoo) Bar(cb MyCallback) { 
} 

その後、そのライブラリを使用しているクライアントコードから、コールバックを使用して呼び出す必要があります。

cf := &CoolFoo{} 

cf.Bar(func(f packageName.Foo) { 
}) 

しかし、私はむしろ私のIDEで、より自己文書化コード、および適切なタイプヒンティングを持っているでしょうので、私のような、実装タイプを使用して、それを呼び出すようにしてみてください。私は、インターフェイスタイプを使用して、それを呼び出した場合、それは動作しますこの:

cannot use func literal (type func(packageName.CoolFoo)) as type packageName.MyCallback in argument to cf.Bar

ことが可能とされていないか、私はいくつかのダミーのミスを作っています:エラーが発生して、コンパイルに失敗し

cf := &CoolFoo{} 

cf.Bar(func(f packageName.CoolFoo) { 
}) 

?私はdevデベロッパではあまり経験がありません。私は見回してみましたが、ここで解決策を見つけることができませんでした。私が見つけた何

はFooのか、私が欲しいものにコールバックでキャストし、インターフェイス{}として渡しているが、私はそれが任意のヘルプ厄介

感謝を感じているとして、それを避けたいです

答えて

3

関数のシグニチャはfunc(f Foo)なので、と正確にはを渡す必要があります。理由は簡単です:あなたのメソッドがそのシグネチャのコールバック関数を期待している場合、Fooを実装する任意の型をに渡すことができます。 CoolFooしか受け付けられていない関数を渡した場合、呼び出し元は定義した型が許可するので、BadFooを渡すことができます。したがって、コンパイラは型が正確に一致することを要求します。同様に、コールバック関数が具体的な型にキャストしようとしたが、渡された型ではない場合、コードでサポートされていないことを前提としているため、失敗します。

コールバックがCoolFooにしか届かない場合は、署名に使用するタイプにする必要があります。 CoolFooBadFooのそれぞれがそれぞれのタイプをコールバックに渡すだけの場合は、2つの異なるコールバックシグネチャが必要になることがあります。彼らが本当に交換可能な場合、あなたが記述するケース(具体的にはCoolFooを取る関数)は言語に問題ではなく、デザインには問題があります。

関連する問題