Khi Rob Pike nói rằng, Go Go nói về sáng tác, chính xác thì ý anh là gì? [đóng cửa]


12

Từ ít hơn theo cấp số nhân

Nếu C ++ và Java là về phân cấp kiểu và phân loại các loại, thì Go là về thành phần.

Câu trả lời:


13

Anh ta có nghĩa là nơi bạn sử dụng thứ gì đó theo thứ tự:

class A : public B {};

trong một cái gì đó như Java hoặc C ++, trong Go bạn sẽ sử dụng (một cái gì đó tương đương):

class A {
    B b;
};

Vâng, điều này cung cấp khả năng giống như thừa kế. Hãy mở rộng ví dụ trên một chút:

struct B {
    int foo() {}
};

struct A { 
    B b;
};

A a;

a.foo();  // not allowed in C++ or Java, but allowed in Go.

Tuy nhiên, để làm điều này, bạn sử dụng một cú pháp không được phép trong C ++ hoặc Java - bạn để đối tượng được nhúng mà không có tên của chính nó, vì vậy nó giống như:

struct A {
   B;
};

1
Tôi tò mò, tôi làm điều đó trong C ++ (thích sáng tác). Có phải cung cấp các tính năng giúp tôi soạn thảo khi trong Java / C ++ tôi sẽ phải kế thừa không?
Doug T.

2
@DougT.: Có, tôi đã chỉnh sửa trong một ví dụ cho thấy ý tưởng chung về (một phần) những gì nó cho phép.
Jerry Coffin

2
Tôi nghĩ rằng điều này bỏ lỡ vấn đề: sự khác biệt không chỉ là một cú pháp ngụ ý bạn sử dụng nhúng để xây dựng phân loại của bạn. Thực tế là việc thiếu phương pháp OOP ghi đè ngăn cản bạn xây dựng phân loại cổ điển của mình và bạn phải sử dụng thành phần thay thế.
Denys Séguret

1
@dystroy: So với Java, có lẽ bạn có một điểm. So với C ++, không quá nhiều - bởi vì (ít nhất là trong số những người có đầu mối) những phân loại khổng lồ đó đã được nhìn thấy lần cuối cách đây gần 20 năm.
Quan tài Jerry

1
@dystroy: Bạn vẫn chưa hiểu. Một hệ thống phân cấp ba cấp độ trong C ++ hiện đại bên cạnh chưa từng thấy. Trong C ++, bạn sẽ thấy những người trong thư viện iostreams và hệ thống phân cấp ngoại lệ - nhưng gần với nơi khác. Nếu thư viện iostreams được thiết kế ngày hôm nay, tôi nghĩ sẽ an toàn khi nói rằng nó cũng sẽ không như vậy. Điểm mấu chốt: các đối số của bạn hiển thị ít hơn về C ++ so với việc bạn không liên lạc với nó như thế nào. Cho rằng bạn đã không sử dụng nó trong nhiều thập kỷ, điều đó có ý nghĩa. Điều không có ý nghĩa là cố gắng nói C ++ được sử dụng như thế nào dựa trên trải nghiệm ngày đó.
Jerry Coffin

8

Câu hỏi / vấn đề này là loại tương tự như câu hỏi này .

Trong Go, bạn không thực sự có OOP.

Nếu bạn muốn "chuyên môn hóa" một đối tượng, bạn thực hiện nó bằng cách nhúng, đó là một thành phần, nhưng với một số tính năng làm cho nó tương tự một phần với sự kế thừa. Bạn làm như thế này:

type ConnexionMysql struct {
    *sql.DB
}

Trong mẫu này, ConnexionMysql là một loại chuyên môn của * sql.DB và bạn có thể gọi ConnexionMysql các hàm được định nghĩa trên * sql.DB:

type BaseMysql struct {
    user     string
    password string
    database string
}

func (store *BaseMysql) DB() (ConnexionMysql, error) {
    db, err := sql.Open("mymysql", store.database+"/"+store.user+"/"+store.password)
    return ConnexionMysql{db}, err
}

func (con ConnexionMysql) EtatBraldun(idBraldun uint) (*EtatBraldun, error) {
    row := con.QueryRow("select pv, pvmax, pa, tour, dla, faim from compte where id=?", idBraldun)
    // stuff
    return nil, err
}

// somewhere else:
con, err := ms.bd.DB()
defer con.Close()
// ...
somethings, err = con.EtatBraldun(id)

Vì vậy, ngay từ cái nhìn đầu tiên, bạn có thể nghĩ rằng thành phần này là công cụ để thực hiện phân loại thông thường của bạn.

Nhưng

nếu một hàm được định nghĩa trên * sql.DB gọi các hàm khác được định nghĩa trên * sql.DB, thì nó sẽ không gọi các hàm được định nghĩa lại trên ConnexionMysql ngay cả khi chúng tồn tại.

Với sự kế thừa cổ điển, bạn thường làm một cái gì đó như thế này:

func (db *sql.DB) doComplexThing() {
   db.doSimpleThing()
   db.doAnotherSimpleThing()
}

func (db *sql.DB) doSimpleThing() {
   // standard implementation, that we expect to override
}

Đó là, bạn xác định doComplexThing trên siêu hạng là một tổ chức theo các cuộc gọi của các chuyên ngành.

Nhưng trong Go, điều này sẽ không gọi chức năng chuyên biệt mà là chức năng "siêu lớp".

Vì vậy, nếu bạn muốn có một thuật toán cần gọi một số hàm được xác định trên * sql.DB nhưng được định nghĩa lại trên ConnexionMyQuery (hoặc các chuyên ngành khác), bạn không thể định nghĩa thuật toán này là hàm của * sql.DB nhưng phải xác định nó ở nơi khác và chức năng này sẽ chỉ soạn các cuộc gọi đến chuyên môn được cung cấp.

Bạn có thể làm điều đó như thế này bằng các giao diện:

type interface SimpleThingDoer {
   doSimpleThing()
   doAnotherSimpleThing()
}

func doComplexThing(db SimpleThingDoer) {
   db.doSimpleThing()
   db.doAnotherSimpleThing()
}

func (db *sql.DB) doSimpleThing() {
   // standard implementation, that we expect to override
}

func (db ConnexionMySQL) doSimpleThing() {
   // other implemenation
}

Điều này khá khác biệt so với việc ghi đè cổ điển của hệ thống phân cấp lớp.

Đặc biệt, rõ ràng bạn không thể trực tiếp có một cấp thứ ba kế thừa việc thực hiện chức năng từ cấp thứ hai.

Trong thực tế, bạn sẽ kết thúc bằng cách sử dụng hầu hết các giao diện (trực giao) và để chức năng soạn thảo các cuộc gọi trên một triển khai được cung cấp thay vì có "siêu lớp" thực hiện các cuộc gọi đó.

Theo kinh nghiệm của tôi, điều này dẫn đến sự thiếu vắng thực tế của hệ thống phân cấp sâu hơn một cấp.

Thông thường, trong các ngôn ngữ khác, bạn có phản xạ, khi bạn thấy rằng khái niệm A là một chuyên môn của khái niệm B, để xác định thực tế này bằng cách tạo một lớp B và một lớp A là một lớp con của B. Thay vì tạo ra của bạn chương trình xung quanh dữ liệu của bạn, bạn dành thời gian tái tạo phân loại đối tượng trong mã của mình, theo nguyên tắc đây là thực tế.

Trong Go bạn không thể xác định một thuật toán chung và chuyên môn hóa nó. Bạn phải xác định một thuật toán chung và đảm bảo nó chung và hoạt động với các cài đặt giao diện được cung cấp.

Đã bị kinh hoàng bởi sự phức tạp ngày càng tăng của một số cây phân cấp mà các lập trình viên đã tạo ra các bản hack phức tạp để cố gắng đáp ứng một thuật toán mà logic của nó cuối cùng bao hàm tất cả các cấp, tôi nói rằng tôi hài lòng với logic Go đơn giản hơn, ngay cả khi nó buộc bạn nghĩ thay vì chỉ thống nhất các khái niệm về mô hình ứng dụng của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.