2015-05-22 17 views
48

Tôi đang bối rối là tại sao này thất bại trong việc biên dịch với:Tại sao không thể giao diện được thực hiện với máy thu trỏ

không thể loại khẳng định: Faz không thực hiện Foo (phương pháp Bar có con trỏ receiver)

nếu tôi làm cho người nhận cho Faz.Bar một giá trị Faz chứ không phải là một con trỏ Faz sau đó nó biên dịch tốt, nhưng tôi nghĩ rằng nó là luôn luôn tốt hơn để có thu trỏ nên giá trị không được sao chép xung quanh?

package main 

import (
    "log" 
) 

func main() { 
    foo := New().(Faz) 
    log.Println(foo) 
} 

type Foo interface { 
    Bar() string 
} 

func New() Foo { 
    return &Faz{} 
} 

type Faz struct { 
} 

func (f *Faz) Bar() string { 
    return `Bar` 
} 
+5

[Xem bài đăng này] (http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go). –

+3

Giống như một lưu ý phụ: bài viết được tham chiếu bởi @KerrekSB rất hữu ích cho tôi khi hiểu rằng khi Go phàn nàn "MyFoo không thực hiện Foo (phương thức Bar có bộ nhận con trỏ)", điều đó không có nghĩa là bạn không thể sử dụng một người nhận con trỏ. Nó có nghĩa là một trong hai _none_ của các phương thức 'MyFoo' thực hiện' Bar' sẽ có bộ thu con trỏ, hoặc _all_ của chúng phải. Đó là một vấn đề khác với @ 0xor1, nhưng những người khác có thể tìm thấy câu hỏi này bởi vì họ đang trộn các kiểu người nhận của họ (như tôi) và không hiểu được lỗi họ đang gặp phải. – Hephaestus

Trả lời

51

Vì đó là *Faz không Faz.

func main() { 
    foo := New().(*Faz) 
    log.Println(foo) 
} 
+0

Tôi chắc chắn rằng tôi đã thử rằng: s, cũng cảm ơn :) – 0xor1

+4

Họ có thể là * Faz hoặc Faz nhưng tất cả họ phải phù hợp. Xác định tất cả Faz nếu bạn định trả về Faz {} 'hoặc * Faz nếu bạn định' return & Faz {} '. Làm thế nào họ duy trì trạng thái được coi là một chi tiết thực hiện mà bạn về cơ bản là ẩn từ người dùng. –

4

Tôi nghĩ câu trả lời cho câu hỏi này cần phải có cách tiếp cận hướng tới ngữ pháp hơn và cách thực hiện nó thông qua kỹ nghệ phần mềm. (Xin lỗi các quá đơn giản hóa)


Lần đầu tiên một đoạn hồi tưởng nhanh chóng của những gì types?
Chúng chỉ là các khối bộ nhớ với logic trình biên dịch ở trên cùng. Điều gì làm cho một array khác với một string là trình biên dịch cho phép chúng ta làm gì với các khối bộ nhớ đó. (Hãy suy nghĩ sâu hơn và bạn có thể bắt đầu nhận ra sự khác biệt thực sự giữa các ngôn ngữ strongly typeddynamically typed.)

Bây giờ, bạn cần nhận ra rằng các con trỏ là kiểu riêng của chúng.
*variable là một khối bộ nhớ khác (còn gọi là loại) hơn variable. Nó chỉ là trình biên dịch luôn luôn giả định rằng nội dung của *variable luôn là một địa chỉ cho một khối bộ nhớ kiểu ở bên phải của khai báo cùng với các hạn chế/tính năng khác mà nó áp đặt.

Sau đó, hãy tóm tắt lại giao diện là gì.
Định nghĩa khoa học giả: Một tập hợp các yêu cầu cho bất kỳ công dân hạng nhất nào thuộc một loại cụ thể. Dịch sang các phần mềm engineering- bất kỳ khối bộ nhớ (các loại) có cấu trúc bộ nhớ cùng (nghĩ lại structure packing) liên quan đến nó như mô tả trong hợp đồng (interface) có thể được thông qua xung quanh như với tên loại rằng hợp đồng đề cập.


Bây giờ bạn có thể bắt đầu nhận ra rằng khi bạn nói

func (f *Faz) Bar() string là 'khối của bộ nhớ giữ một chức năng, nơi f' f s loại là một con trỏ đến Faz

nơi các khu vực

func (f Faz) Bar() string là khối bộ nhớ của f, trong đó f là loại Faz

Vì vậy, khi bạn nói rằng biến số *Faz thỏa mãn hợp đồng, thì làm cách nào bạn có thể giả định rằng biến số Faz sẽ đủ điều kiện làm loại giao diện trong mã? Chọn người thỏa mãn hợp đồng của bạn và chỉ loại đó có thể giả định loại giao diện trong mã của bạn.

+0

Tôi không đồng ý với lời giải thích của bạn, chương trình sau làm việc (loại * foo đáp ứng String() được xác định cho loại foo): gói chính nhập khẩu ( \t "fmt" ) loại foo struct {} func (f foo) string() {string \t trở lại "111" } func main() { \t f: = foo {} \t a: = & foo {} \t var s fmt.Stringer \t s = a \t s = f \t fmt.Println (f.String(), a.String(), s) } –

+0

Xem https://golang.org/ref/spec#Method_sets –

Các vấn đề liên quan