В Go, если тип T2 основан на типе T1, существует ли какое-либо «наследование» от T1 до T2? - PullRequest
8 голосов
/ 26 июня 2011

Если type T2 основано на type T1, кроме совместного использования одних и тех же полей данных, существует ли какая-либо связь между T1 и T2?

package main
import "fmt"

type T1 struct { s string }
func (v *T1) F1() string { return v.s }

type T2 T1
func (v *T2) F2() string { return v.s }

func main() {
        var t1 = T1{ "xyz" }
        var t2 = T2{ "pdq" }
        s0 := t2.F1()                   // error - expected ok
        s1 := ((*T1)(&t2)).F1()         // ok - expected
        s2 := ((*T2)(&t1)).F2()         // ok - not expected
        fmt.Println( s0, s1, s2 )
}

Мое понимание здесь отсутствует

  1. надеялся, что T2 унаследует методы T1, но это не так.

  2. ожидал, что T2 может быть приведен к T1, поскольку он был получен из T1

  3. был удивлен, что T1 может быть приведен к T2, но это так.

  4. кажется, что отношения между T1 и T2 полностью симметричны - я не могу найти ничего, что нарушает симметрию, несмотря на тот факт, что одно на самом деле происходит от другого - или это иллюзия?

(ПРИМЕЧАНИЕ: я не критикую или оцениваю - я полностью уважаю принятые решения - просто проверка, я понимаю, что есть, что для меня нелогично - я уверен, что я не единственный один!)

Ответы [ 4 ]

8 голосов
/ 26 июня 2011

Go не поддерживает объектно-ориентированное наследование типов.

Является ли Go объектно-ориентированным языком?

Почему нет наследования типов?

Метод связан с одним конкретным типом.

A Объявление метода связывает идентификатор с методом.Считается, что метод связан с базовым типом и виден только в селекторах для этого типа.

Вы можете преобразовать между типами T1 и T2.

Значение x может быть преобразовано в тип T [когда] тип x и T имеют идентичные базовые типы.

Например,

package main

import (
    "fmt"
)

type T1 struct{ i int }

func (t T1) String() string { return "T1" }

type T2 T1

func (t T2) String() string { return "T2" }

func main() {
    t1 := T1{1}
    t2 := T2{2}
    fmt.Println(t1, t2)
    c1 := T1(t2)
    c2 := T2(t1)
    fmt.Println(c1, c2)
    t1 = T1(c2)
    t2 = T2(c1)
    fmt.Println(t1, t2)
}

Output:
T1 T2
T1 T2
T1 T2
1 голос
/ 26 июня 2011

Не уверен, поможет ли это вам, но посмотрите на «анонимные поля», описанные, например, в «Перейти к программистам на C ++» , в разделе «Интерфейсы» - кажется, они предоставляют что-то выглядящеекак дочерние классы.

Но в любом случае, читая учебники по Go, я разработал идею, что авторы Go решительно хотели, чтобы программисты уклонялись от построения цепочек наследования и использовали вместо этого встраивание / делегирование.

0 голосов
/ 26 июня 2011

Я могу объяснить, почему T2 не имеет методов T1.Представьте, что вам нужно отсортировать данные типа T двумя разными способами.По умолчанию используется один способ, поэтому в T вы реализуете методы Len, Less и Swap.Вы можете позвонить sort.Sort(data) и отсортировать данные по умолчанию.Но как отсортировать данные по-другому?

Вы пишете type SortDifferently T и реализуете методы Len, Less и Swap для типа SortDifferently.Если бы у SortDifferently были все методы T, вы бы не смогли этого сделать, потому что у Go нет переопределений методов.Но теперь без наследования вы можете написать sort.Sort((SortDifferently)data) для сортировки данных по-другому.

Это способ работы Go.К этому нелегко привыкнуть.

0 голосов
/ 26 июня 2011
s2 := ((*T2)(&t1)).F2()         // ok - not expected

работает, потому что вы приводите его к типу T2, и это позволяет F2.Так что ожидается работа.Затем вызывается функция F2 для вашего T2 объекта t1, который возвращает t1.s.

s0 := t2.F1()                   // error - expected ok

Для этого я не могу сказать вам наверняка, но только дам вам правдоподобную идеюа также:

F1 - это метод для типа T1.Поскольку t2 не относится к типу T1, вы не можете вызвать F1 на t2.Итак, как вы заметили, разделяются только поля данных, а не методы этих типов.

Также см. Go для программистов на C ++ , в которых говорится:

Методы определены для именованных типов.Если вы преобразуете значение в другой тип, новое значение будет иметь методы нового типа, а не старого типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...