英文:
How to make this Go abstract type work?
问题
package main
import "fmt"
type IA interface {
A()
B()
}
type AbsA struct {
IA
}
type CA struct {
AbsA
}
func (a CA) B() {
fmt.Println("Show B")
}
func (a AbsA) A() {
fmt.Println("Show A")
a.B()
}
func t7() {
var a IA
a = CA{}
a.A()
}
func main() {
t7()
}
运行这段代码会导致空指针异常,因为当 AbsA
调用 B()
时,它会使用嵌入的 IA
,但 IA
是一个接口。
有没有办法让这段代码正常工作?
编辑
我尝试创建一个抽象的超类 AbsA
,它只实现接口的一部分,但它需要使用其他函数。A
是 AbsA
的子类,只实现接口的剩余部分。
但这看起来不太好,有没有其他方法可以实现这个需求?实际上,我只是想做类似这样的事情:
func (a IA) A() {
fmt.Println("Show A")
a.B()
}
但是 Go 不能使用接口作为接收器。
英文:
package main
import "fmt"
type IA interface {
A()
B()
}
type AbsA struct {
IA
}
type CA struct {
AbsA
}
func (a CA) B() {
fmt.Println("Show B")
}
func (a AbsA) A() {
fmt.Println("Show A")
a.B()
}
func t7() {
var a IA
a = CA{}
a.A()
}
func main() {
t7()
}
Running this will get a nil pointer panic, because when AbsA
calls B()
, it will use the embedded IA
, but IA
is an interface.
Is there any way to make this work?
EDIT
I try to make a abstract super class, AbsA only implement part of interface, but it need to use other functions,A is a subclass of AbsA, only implement the rest part of interface.
But this looks bad, is there any other way to do this ? actually , I just want to do something like this
func (a IA)A(){
fmt.Println("Show A")
a.B()
}
but go can not use a interface as a receiver.
答案1
得分: 3
我不知道你想要实现什么,但是如果你正在定义带有嵌入接口的结构体,你需要对它们进行初始化。
http://play.golang.org/p/C32yWfNDRp
var a IA
a = CA{
AbsA: AbsA{
IA: CA{},
},
}
a.A()
如果你期望面向对象的继承行为,Go语言并不提供这种功能。嵌入只是一种自动委托的形式。
英文:
I don't know what you're trying to accomplish, but if you're defining structs with embedded interfaces, you need to initialize them.
http://play.golang.org/p/C32yWfNDRp
var a IA
a = CA{
AbsA: AbsA{
IA: CA{},
},
}
a.A()
If you're expecting OOP inheritance behavior, Go doesn't provide that. Embedding is only a form of automatic delegation.
答案2
得分: 1
不,至少不是你在这里设计的方式。我不太确定你试图实现什么,但这是一种非常糟糕的嵌入使用方式。它不起作用的原因是CA
类型依赖于嵌入的AbsA
类型的A()
方法,该方法又调用了一个"方法b",但实际上B()
的唯一实现是以CA作为接收类型的,所以一旦你调用嵌入类型的A()
实现,它就无法调用回嵌入类型的B()
实现。
你把嵌入当作是双向的,但实际上嵌入类型知道所有嵌入对象的方法,而嵌入对象对嵌入者一无所知。在我个人看来,这应该生成一个编译器错误。也许在将来的版本中会有(如果我可以在编译时确定你将始终获得运行时错误,那么编译器也应该能够确定,对吗?)。
现在,你要么需要使用类型为Absa
的接收者来实现B()
,要么添加另一个以类型CA
为接收者的A()
实现。我不太确定你试图实现什么,所以无法确定最佳的解决方案是什么。请注意,如果我将其与传统的面向对象继承相关联,我会将你的代码描述为试图从父类中访问子类的属性,显然是不可能的。Absa
永远无法调用嵌入它的类型定义的B()
实现。就像试图从父类使用在继承类型中定义的方法一样,这是行不通的,也没有意义,只是在大多数面向对象编程语言中,你会得到一个编译时错误。
英文:
No, at least not as you have it designed here. I'm not entirely sure what you're trying to accomplish but this is a very very poor use of embedding. The reason it doesn't work is because the CA
type relies on the embedded AbsA
type for method A()
which then calls a 'method b' but the only actual implementation of B()
has CA as the receiving type so once you've calling into the embedded types implementation of A()
it can't call back up to the embedding types implementation of B()
.
You're treating embedding as if it's a two way street but in reality the embedding type knows all the methods on it's embed and the embed knows nothing about the embeddor. In my personal opinion, this should generate a compiler error. Perhaps in a future release it will (if I can tell at compile time that you will get a run-time error 100% of the time the compiler should able to too, right?).
As it is now you either need to implement B()
with a receiver of type Absa
or add another implementation of A()
with a receiver of type CA
. I'm not really sure what you're trying to accomplish so I can't say what the best course of action is. Note that if I were relating this to traditional OOP inheritance I would describe your code as attempting to access properties of a child class from within a parent class, clearly it's not possible. Absa
will never be able to call up to an implementation of B()
defined for the type embedding it. Just like trying to use a method defined on an inheriting type from the parent would never work or make sense only in most of the OOP languages you would get a compile time error.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论