2017-11-06 3 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) 

하지만이 일이 제대로 실행 (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

이동에는 상속이 없으므로 "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 런타임은 특정 버전을 몇 가지 버전으로 다시 변경하여 구조 포인터와 마찬가지로 인터페이스 포인터를 자동으로 비 참조 화하지 않고 사용을 저지했습니다. 압도적 인 대부분의 경우 인터페이스에 대한 포인터는 인터페이스가 작동하는 방법에 대한 오해를 반영합니다.