2017-11-06 15 views
-1

このコードが正しく実行されません:行くの継承やポリモーフィズム

package main 
import "fmt" 

type Human interface { 
    myStereotype() string 
} 

type Man struct { 
} 

func (m Man) myStereotype() string { 
    return "I'm going fishing." 
} 

type Woman struct { 
} 

func (m Woman) myStereotype() string { 
    return "I'm going shopping." 
} 
func main() { 
    var m *Man 
    m = new (Man) 
    w := new (Woman) 

    var hArr []*Human 

    hArr = append(hArr, m) 
    hArr = append(hArr, w) 

    for n, _ := range (hArr) { 

     fmt.Println("I'm a human, and my stereotype is: ", 
       hArr[n].myStereotype()) 
    } 
} 

それはして存在している:

tmp/sandbox637505301/main.go:29:18: cannot use m (type *Man) as type *Human in append: 
*Human is pointer to interface, not interface 
tmp/sandbox637505301/main.go:30:18: cannot use w (type *Woman) as type *Human in append: 
*Human is pointer to interface, not interface 
tmp/sandbox637505301/main.go:36:67: hArr[n].myStereotype undefined (type *Human is pointer to interface, not interface) 

しかし、この1は正常に動作します(VARのハーは、[] *ヒトは、VaRのハールの[に書き換えられますヒト):

package main 
import "fmt" 

type Human interface { 
    myStereotype() string 
} 

type Man struct { 
} 

func (m Man) myStereotype() string { 
    return "I'm going fishing." 
} 

type Woman struct { 
} 

func (m Woman) myStereotype() string { 
    return "I'm going shopping." 
} 
func main() { 
    var m *Man 
    m = new (Man) 
    w := new (Woman) 

    var hArr []Human // <== !!!!!! CHANGED HERE !!!!!! 

    hArr = append(hArr, m) 
    hArr = append(hArr, w) 

    for n, _ := range (hArr) { 

     fmt.Println("I'm a human, and my stereotype is: ", 
       hArr[n].myStereotype()) 
    } 
} 

出力がOKです:

I'm a human, and my stereotype is: I'm going fishing. 
I'm a human, and my stereotype is: I'm going shopping. 

そして、なぜ私は理解できません。 mとwがポインタであるため、hArrをHumanのポインタの配列として定義すると、コードが失敗するのはなぜですか?

はあなたの主な問題は、あなたがインターフェイスへのポインタを使用していることであるあなたの説明

+3

Goには継承がないため、 "is a"型の多型がありません。 – JimB

+0

[インタフェースを使用した任意のタイプのキューの作成](https://stackoverflow.com/questions/35595810/using-interfaces-to-create-a-queue-for-arbitrary-types)の可能な複製 – IanAuld

答えて

4

いただきありがとうございます。 this questionへの私の答えには、その違いに関するいくつかの詳細が含まれています。十分に言えば、インタフェースへのポインタはほとんど常にエラーです。

Human*Humanではない)に格納すると、インターフェイスに問題なくポインタを格納できるため、正常に動作します。実際には、インターフェイスに格納された値は格納されている型のポインタメソッドにアクセスできないので、ポインタをインターフェイスに格納することをデフォルトにしたいとします。インターフェースは型を保持する単なるバケットであり、その型が構造体か構造体へのポインタかは関係ありません。一方、インタフェースへののポインタは、のインタフェースであり、インタフェースと同じ暗黙のフルフィルメントシステムを持っていません。これは、関数として変数*func()を使用できないこととほぼ同じです。それはポインタであり、関数ではありません。

TL; DR:インターフェイスへのポインタを使用しないでください。これはほとんど役に立たず、一般的にはどのインタフェースが誤解されているかを反映しています。

1

インターフェイスは、タイプよりもAPI定義に似ていると考えるのが役立ちます。インターフェイスを満たすものは、すでに構造体またはポインタである可能性があるため、インターフェイスポインタを使用する必要はありません。 this excellent answerに記載されているとおり:

インターフェイスへのポインタはほとんど役に立ちません。実際、Goランタイムは、いくつかのバージョンを、構造ポインタの場合と同様に、自動的にインタフェースポインタを逆参照しないように変更し、その使用を阻止しました。圧倒的多数のケースでは、インタフェースへのポインタは、インタフェースの動作方法の誤解を反映しています。