ホームページ  >  記事  >  バックエンド開発  >  X は Y を実装していません (...メソッドにはポインタ レシーバがあります)

X は Y を実装していません (...メソッドにはポインタ レシーバがあります)

WBOY
WBOY転載
2024-02-12 23:27:08869ブラウズ

X 没有实现 Y(...方法有一个指针接收器)

この記事では、PHP エディターの Xiaoxin が、X による Y の実装の失敗に関する問題について説明します。この問題では、ポインター レシーバーのアプローチを使用しました。この方法を通じて、X が Y を達成できない理由をよりよく理解し、この問題を解決する方法を見つけることができます。次のコンテンツでは、この問題について詳しく説明し、いくつかの解決策を提供します。

質問内容

XX は Y を実装していません (...メソッドにはポインタ レシーバがあります)」という質問についてはいくつかの Q&A がありますが、私にとっては、彼らは別のことについて話しているようで、私の特定の状況には当てはまりません。

そこで、質問を非常に具体的にする代わりに、広く抽象的な質問にします。このエラーが発生する原因となる可能性のある状況がいくつかあるようですが、誰かがそれを要約できますか?

この問題を回避するにはどうすればよいですか?また、この問題が発生した場合はどのような可能性がありますか?ありがとう。

回避策

このコンパイル時エラーは、

concrete 型をインターフェイス型に割り当てたり渡したり (または変換) しようとしたときに発生しますが、型自体はこのインターフェイスを実装すると、型への ポインター のみが実装されます。

短い概要: 変数への代入 インターフェイス型は、割り当てられた値が、割り当て先のインターフェイスを実装する場合に有効です。その メソッド セット がインターフェイスのスーパーセットである場合、それを実装します。ポインター型のメソッド セットには、ポインター レシーバーと非ポインター レシーバーを持つメソッドが含まれます。非ポインター型のメソッド セット のみ には、非ポインター レシーバーを持つメソッドが含まれます。 例を見てみましょう:

リーリー

stringer

インターフェイス タイプには、メソッド string() が 1 つだけあります。インターフェイス値 stringer に格納されている値には、このメソッドが必要です。また、mytype を作成し、pointer レシーバーを備えたメソッド mytype.string() を作成しました。これは、string() メソッドが *mytype 型の メソッド セット に含まれていますが、mytype には含まれていないことを意味します。

mytype

の値を stringer 型の変数に代入しようとすると、次のエラーが表示されます: リーリー しかし、

*mytype

型の値を stringer に代入しようとすると、すべて正常に動作します。 リーリー 期待どおりの結果が得られます (go playground

で試してください):

リーリー したがって、このコンパイル時エラーが発生するには、次のものが必要です:

割り当てられた (または渡された、または変換された)

非ポインター
    特定の型の値
  • 割り当てられる (または渡されるか変換される) インターフェイスの種類
  • 具象型にはインターフェイスに必要なメソッドがありますが、
  • ポインタ レシーバもあります
  • 問題解決の可能性:

値へのポインターを使用する必要があり、そのメソッド セットにはポインター レシーバーを持つメソッドが含まれます

    または、レシーバーの型を
  • 非ポインター
  • に変更する必要があります。そのため、非ポインター具象型のメソッド セットにもメソッドが含まれます (これにより、インターフェイスが満たされます)。メソッドで値を変更する必要がある場合、非ポインター レシーバーはオプションではないため、これは可能な場合と不可能な場合があります。
  • 構造と埋め込み

構造体を使用して

を埋め込む場合、通常は「あなた」がインターフェースを実装する (メソッド実装を提供する) のではなく、

struct に埋め込まれた型です。この例のように: リーリー mytype2 のメソッド セットには

mytype

に埋め込まれた string() メソッドが含まれておらず、* のみが含まれているため、再コンパイル時にエラーが発生しました。 mytype2 メソッドが設定されているため、次のメソッドが有効です ( のプレイグラウンドに移動します): リーリー *mytype を埋め込み、

非ポインター

mytype2 を使用するだけでも機能させることができます ( のプレイグラウンドに移動します)。 リーリー また、何を埋め込んだとしても (mytype または *mytype

)、ポインター

*mytype2 を使用すると、常に機能します (# で) # #ゴガン): リーリー 仕様内の関連セクション ( 構造タイプ セクションから):

给定一个结构体类型 s 和一个名为 t 的类型,提升的方法包含在该结构体的方法集中,如下所示:

  • 如果 s 包含匿名字段 t,则 s*s 的方法集均包含接收者为 t 的提升方法。 *s 的方法集还包括接收者 *t 的提升方法。
  • 如果 s 包含匿名字段 *t,则 s*s 的方法集都包含接收者为 t*t 的提升方法。

换句话说:如果我们嵌入一个非指针类型,非指针嵌入器的方法集只能获取具有非指针接收器的方法(来自嵌入类型)。

如果我们嵌入一个指针类型,非指针嵌入器的方法集将获取具有指针和非指针接收器的方法(来自嵌入类型)。

如果我们使用指向嵌入器的指针值,则无论嵌入类型是否是指针,指向嵌入器的指针的方法集始终都会获取具有指针和非指针接收器的方法(从嵌入类型)。

注意:

有一个非常相似的情况,即当您有一个包含 mytype 值的接口值时,并且您尝试 类型断言 另一个接口值,stringer。在这种情况下,由于上述原因,断言将不成立,但我们会得到一个略有不同的运行时错误:

m := mytype{value: "something"}

var i interface{} = m
fmt.println(i.(stringer))

运行时恐慌(在 go playground 上尝试一下):

panic: interface conversion: main.mytype is not main.stringer:
    missing method string

尝试转换而不是类型断言,我们得到了我们正在讨论的编译时错误:

m := MyType{value: "something"}

fmt.Println(Stringer(m))

以上がX は Y を実装していません (...メソッドにはポインタ レシーバがあります)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。