用复杂合理的模块扩展计算器(使用动态绑定)

我已经制作了可以计算整数和实数的计算器(我用 go 完成了)。然后我想通过添加这些模块来计算复数和有理数。(它还可以计算类型何时混合)如果我每次(运行时)检查操作数的类型并处理每种情况,这很容易,但我想用动态绑定来解决它。伙计们,你能告诉我如何解决这个问题的想法吗



哔哔one
浏览 115回答 1
1回答

宝慕林4294392

我认为通过动态类型,您可能指的是在例如 C++ 和 Java 中,动态绑定本质上是对可以指向派生类的基类的引用(因为派生类“是”基类)。有人可能会说,基类定义了派生类变形的接口。如果派生类替换了基类的方法,对基类的引用仍然可以访问派生类中的那些方法。基类可以定义一些方法来为其派生类提供一些“基”功能。如果这些类没有重新定义方法,则可以调用基类的方法。在 go 中,这两个概念都存在,但它们完全不同。Go 有一个明确的interface关键字来定义方法签名但没有方法。如果任何值具有具有相同签名的同名方法,则任何值都会隐式满足该接口。type LivingBeing interface {    TakeInEnergy()    ExpelWaste()}接口类型成为代码中的有效类型。我们可以将接口传递给函数,并且在不知道满足该接口的类型的情况下,可以调用它的方法:func DoLife(being LivingBeing) {   being.TakeInEnergy()   being.ExpelWaste()}这是有效的代码,但不是完整的代码。与其他语言的基类不同,接口不能定义函数,只能定义它们的签名。它纯粹是一个接口定义。 我们必须将满足接口的类型与接口本身分开定义。type Organism struct{}func (o *Organism) TakeInEnergy() {}func (o *Organism) ExpelWaste() {}我们现在有一个organism满足LivingBeing. 它有点像基类,但如果我们想在它的基础上构建,我们不能使用子类化,因为 Go 没有实现它。但是 Go 确实提供了类似的东西,称为嵌入类型。在这个例子中,我将定义一个新的有机体 Animal,它ExpelWaste()从 中提取LivingBeing,但定义了自己的TakeInEnergy():type Animal struct {    Organism  // the syntax for an embedded type: type but no field name}func (a *Animal) TakeInEnergy() {    fmt.Printf("I am an animal")}从该代码中不明显的是,因为Animal'sOrganism不是命名字段,所以它的字段和方法可以直接从Animal. 这几乎就像Animal“是一个”有机体。然而,它*不是*一个有机体。它是一种不同的类型,将对象嵌入视为语法糖以自动将Organism的字段和方法提升为Animal.由于 go 是静态和显式类型的,DoLife因此不能接受 anOrganism然后传递 an Animal:它没有相同的类型:/* This does not work.  Animal embeds organism, but *is not* an organism */func DoLife(being *Organism) {   being.TakeInEnergy()   being.ExpelWaste()}func main() {    var a = &Animal{Organism{}}    DoLife(&Animal{})}cannot use &Animal{} (type *Animal) as type *Organism in argument to DoLife这就是interface存在的原因——因此Organismand Animal(实际上,甚至Plantor ChemotrophBacteria)都可以作为 LivingBeing.综上所述,这是我一直在使用的代码:package mainimport "fmt"type LivingBeing interface {    TakeInEnergy()    ExpelWaste()}type Organism struct{}func (o *Organism) TakeInEnergy() {}func (o *Organism) ExpelWaste() {}type Animal struct {    Organism}func DoLife(being LivingBeing) {    being.TakeInEnergy()    being.ExpelWaste()}func (a *Animal) TakeInEnergy() {    fmt.Printf("I am an animal")}func main() {    var a = &Animal{Organism{}}    DoLife(a)}有几个注意事项:从语法上讲,如果你想声明一个嵌入的文字,你必须显式地提供它的类型。在我的示例Organism中,没有任何字段,因此无需声明任何内容,但我仍然将显式类型留在那里以指向正确的方向。DoLife可以调用TakeInEnergyLivingBeing 的权利,但Organism的方法不能。他们只看到嵌入的Organism.func (o *Organism) ExpelWaste() {    o.getWaste() //this will always be Organism's getWaste, never Animal's}func (o *Organism)getWaste() {}func (a *Animal)getWaste() {    fmt.Println("Animal waste")}同样,如果您只传递嵌入部分,那么它将调用它自己的TakeInEnergy(),而不是Animal; 没有Animal了!func main() {    var a = &Animal{Organism{}}    DoLife(&a.Organism)}总之,定义显式interface并在需要“多态”行为的任何地方使用该类型定义基本类型并将它们嵌入到其他类型中以共享基本功能。不要期望“基本”类型会“绑定”到“派生”类型的函数。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go