Объект добавлен в [] interface {}. Теперь нужно выбрать объект и вызвать соответствующий объект Display () fn - PullRequest
0 голосов
/ 12 июня 2019

Я сделал следующее:

  • Определен «родительский» интерфейс с Display () fn.
  • Создано 2 дочерних структуры, которые реализуют свой соответствующий Display () fn.
  • В main () создал 2 дочерних объекта и добавил их к: availableObjs[]interface{}
  • Теперь в цикле For нужно взять объект и вызвать его соответствующую функцию Display (). Это то место, где я поражен.

Код GoPlayground: https://play.golang.org/p/jdHpueokrEk

Попытка поиска в Интернете.

Тот же код в строке:

package main

import (
    "fmt"
    "reflect"
)

////// Parent Interface which has Display() fn.
type Parent interface {
    Display()
}

// 2 Child structs implementing their Display() fn.
type Child1 struct {
    name1 string
}

type Child2 struct {
    name2 string
}

func (c1 Child1) Display() {
    fmt.Println("c1Name : ", c1.name1)
}

func (c2 Child2) Display() {
    fmt.Println("c2Name : ", c2.name2)
}
////////////////////////////////////////////

// Maintains the created objects
var availableObjs []interface{}

func main() {
    //// Creating 2 objects
    c1 := Child1{"Child1"}
    c2 := Child2{"Child2"}

    // Adding 2 objects to availableObjs
    availableObjs = append(availableObjs, c1)
    availableObjs = append(availableObjs, c2)

    // Now, want to fetch the Object from Interface and call its respective Display() fn.
    for _, obj := range availableObjs {
            fmt.Println("")
        fmt.Println("Obj Got = ",obj)
        fmt.Println("Obj type = ",reflect.TypeOf(obj))
        //obj.Display()        //  <-- Problem Line 
    }
}

Нужно сделать: Нужны входные данные о том, как я могу вызвать функцию Display () после получения объекта из интерфейса массива.

1 Ответ

1 голос
/ 13 июня 2019

Есть два способа сделать это: один, вместо использования пустого интерфейса, вы используете надлежащий родительский интерфейс для объявления среза:

// Maintains the created objects
var availableObjs []Parent

Обратите внимание, что наименование Parent для вашего интерфейса говорит о том, что вы приближаетесь к интерфейсам с концепцией наследования, которую мы не используем в Go. Вы должны думать об интерфейсах больше как о поведении. В этом конкретном случае вы хотите представить поведение чего-либо, способного «отображать», поэтому вы вполне можете назвать интерфейс Displayer.

Это соглашение об именах, добавляющее -er к имени интерфейса, является очень распространенным шаблоном в Go, хотя иногда вы получаете некоторые странные имена:)

В том же смысле структуры Child на самом деле не являются дочерними элементами родительского интерфейса, они просто являются структурами, которые неявно удовлетворяют интерфейсу.

Они могут одновременно удовлетворять любому количеству интерфейсов. Например, если бы у них был метод String (), они бы также удовлетворяли интерфейсу fmt.Stringer.

Теперь второй вариант - использовать утверждение типа, либо с оператором switch, либо с оператором типа:

switch t := obj.(type) {
case Parent:
    t.Display() // note that 't' is the new typed variable
}

Или

t, ok := obj.(Parent)
if ok {
    t.Display()
}

Обратите внимание, что указанную выше переменную ok можно опустить, но в этом случае код будет паниковать, если утверждение типа не совпадает.

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