我正在按照我在网上找到的教程尝试一些OOP-esque Go。
到目前为止,它非常吸引人(让我想起试图强迫OOP进入ANSI-C)。
然而,只有一件事困扰我,我似乎无法解决。
我如何能够反映嵌入结构的类型名称?
我在网上找到的所有信息都说无法反映嵌入结构,因为嵌入式结构无法直接访问它。
这完全准确吗?如果是这样,解决以下问题的正确方法是什么(下面的代码)?
基本上,程序打印出三个单独动物的名称,然后是括号中嵌入结构的类型名称,然后是相应动物的“声音”。
对于名为“Rover”的狗,我会打印出“Rover(动物):BARK BARK”。现在,显然,“罗孚(动物)”并不是特别有用。 理想情况下,这应该是“Rover(Dog)”(嵌入结构的类型名称,而不是嵌入式结构)。
这就是我的问题。我怎么能够反映嵌入结构的类型,所以“流浪者(动物)”变成“流浪者(”狗“),”朱利叶斯(动物)“变成”朱利叶斯(猫)“等?
package main
import (
"fmt"
"reflect"
)
type Animal struct {
Name string
mean bool
}
type AnimalSounder interface {
MakeNoise()
}
type Dog struct {
Animal
BarkStrength int
}
type Cat struct {
Basics Animal
MeowStrength int
}
type Lion struct {
Basics Animal
RoarStrength int
}
func (dog *Dog) MakeNoise() {
dog.PerformNoise(dog.BarkStrength, "BARK")
}
func (cat *Cat) MakeNoise() {
cat.Basics.PerformNoise(cat.MeowStrength, "MEOW")
}
func (lion *Lion) MakeNoise() {
lion.Basics.PerformNoise(lion.RoarStrength, "ROAR!! ")
}
func MakeSomeNoise(animalSounder AnimalSounder) {
animalSounder.MakeNoise()
}
func main() {
myDog := &Dog{
Animal{
Name: "Rover", // Name
mean: false, // mean
},
2, // BarkStrength
}
myCat := &Cat{
Basics: Animal{
Name: "Julius",
mean: true,
},
MeowStrength: 3,
}
wildLion := &Lion{
Basics: Animal{
Name: "Aslan",
mean: true,
},
RoarStrength: 5,
}
MakeSomeNoise(myDog)
MakeSomeNoise(myCat)
MakeSomeNoise(wildLion)
}
func (animal *Animal) PerformNoise(strength int, sound string) {
if animal.mean == true {
strength = strength * 5
}
fmt.Printf("%s (%s): \n", animal.Name, reflect.ValueOf(animal).Type().Elem().Name())
for voice := 0; voice < strength; voice++ {
fmt.Printf("%s ", sound)
}
fmt.Println("\n")
}
答案 0 :(得分:-1)
好的。
然后回答(或者至少尝试)我自己的问题,提供我认为可能是解决这个问题的正确方法(至少是最简单的方法)。
为简洁起见,我改变了
的所有版本func (cat/dog/lion *Cat/*Dog/*Lion) MakeNoise(){}
到
func (animal *Cat/*Dog/*Lion) MakeNoise(){}
据我所知,这不应该真正损害可读性,也不会引入任何副作用。
“MakeNoise()”的所有迭代现在只提供第三个参数 这与嵌入struct的Type name作为字符串相同。
“PerformNoise()”接受该参数(“animalType”)并简单地将其附加到输出
我
fmt.Printf("%s (%s): \n", animal.Name, animalType)
完整的更新代码:
package main
import (
"fmt"
"reflect"
)
type Animal struct {
Name string
Type string
mean bool
}
type AnimalSounder interface {
MakeNoise()
}
type Dog struct {
Animal
BarkStrength int
}
type Cat struct {
Basics Animal
MeowStrength int
}
type Lion struct {
Basics Animal
RoarStrength int
}
func (animal *Dog) MakeNoise() {
animal.PerformNoise(animal.BarkStrength, "BARK", reflect.ValueOf(animal).Type().Elem().Name())
}
func (animal *Cat) MakeNoise() {
animal.Basics.PerformNoise(animal.MeowStrength, "MEOW", reflect.ValueOf(animal).Type().Elem().Name())
}
func (animal *Lion) MakeNoise() {
animal.Basics.PerformNoise(animal.RoarStrength, "ROAR!! ", reflect.ValueOf(animal).Type().Elem().Name())
}
func MakeSomeNoise(animalSounder AnimalSounder) {
animalSounder.MakeNoise()
}
func main() {
myDog := &Dog{
Animal{
Name: "Rover", // Name
mean: false, // mean
},
2, // BarkStrength
}
myCat := &Cat{
Basics: Animal{
Name: "Julius",
mean: true,
},
MeowStrength: 3,
}
wildLion := &Lion{
Basics: Animal{
Name: "Aslan",
mean: true,
},
RoarStrength: 5,
}
MakeSomeNoise(myDog)
MakeSomeNoise(myCat)
MakeSomeNoise(wildLion)
}
func (animal *Animal) PerformNoise(strength int, sound string, animalType string) {
if animal.mean == true {
strength = strength * 5
}
fmt.Printf("%s (%s): \n", animal.Name, animalType)
for voice := 0; voice < strength; voice++ {
fmt.Printf("%s ", sound)
}
fmt.Println("\n")
}
PS:重新迭代。我不想用这种“假的”OOP方式编写我的所有代码。
它增加了大量不必要的抽象,并且需要对流程进行新的设计考虑。
但是,我认为这是尝试语言基本功能集的好方法。