繁体   English   中英

Google Go 中抽象类/方法 (Java) 的等效性

[英]Equivalence of abstract classes/methods (Java) in Google Go

我是 Go 的新手,我想知道如何在 Java 中实现类似于抽象类和方法的结构。 在 Java 中,我会执行以下操作:

abstract class A{

 static method1(){
  ...
  method2();
  ...
 }

 abstract method2();

}

class B extends A{

 method2(){
  ...
 }

}

class C extends A{

 method2(){
  ...
 }

}

我知道接口和结构。 我可以先构建一个接口,然后再构建一个结构来实现 method1。 但是方法2呢? 我知道我可以将一个接口嵌入另一个接口,也可以将一个结构嵌入另一个结构的字段中。 但是我没有看到用这些方法实现我的结构的方法。

我看到的唯一解决方案是在类 B 和类 C 中实现 method1。没有其他方法吗?

注意:当然,就我而言,这不仅仅是一种方法。 此外,我有一个抽象类的层次结构,并不真的想将所有内容都移到“子类”中。

我在互联网上找到的例子大多是每个接口只有一种方法。 如果你们中的一个人能在这里给我一个提示,那就太好了! 谢谢。

您可以拥有复合接口,例如来自io包:

http://golang.org/src/pkg/io/io.go?s=2987:3047#L57

type Reader interface {
    Read(p []byte) (n int, err error)
}
type Writer interface {
    Write(p []byte) (n int, err error)
}

type ReadWriter interface {
    Reader
    Writer
}

作为旁注,不要尝试使用 go 实现 java 代码,尝试学习Go Way

由于 Go 没有 OOP 意义上的static方法,你经常看到这些类型的方法被实现为包级函数:

package mypackage

func() Method1() { ... } // Below I will call it Function instead

这样的包级函数然后将接口作为参数。 在这种情况下,您的代码将如下所示:

package main

import "fmt"

type Methoder interface {
    Method()
}

func Function(m Methoder) {
    m.Method()
}

type StructB struct{}

func (s *StructB) Method() { fmt.Println("StructB") }

type StructC struct{} // You can do some "inheritance" by embedding a base struct

func (s *StructC) Method() { fmt.Println("StructC") }

func main() {    
    b := &StructB{}
    Function(b)    
}

输出:

StructB

这是我实现抽象类的方式,避免遇到循环引用和维护良好的工厂模式的简单方法。

让我们假设我们的组件具有以下包结构

component
  base
    types.go
    abstract.go
  impl1
    impl.go
  impl2
    impl.go
  types.go
  factory.go

定义组件的定义,在本例中将在此处定义:

组件/types.go

package component

type IComponent interface{
    B() int
    A() int
    Sum() int
    Average() int
}

现在让我们假设我们想要创建一个仅实现SumAverage的抽象类,但在这个抽象实现中,我们希望能够使用已实现的AB返回的值

为此,我们应该为抽象实现的抽象成员定义另一个接口

组件/基础/types.go

package base

type IAbstractComponentMembers {
    A() int
    B() int
}

然后我们可以继续实现抽象的“类”

组件/基础/abstract.go

package base

type AbstractComponent struct {
    IAbstractComponentsMember
}

func (a *AbstractComponent) Sum() int {
    return a.A() + a.B()
}

func (a *AbstractComponent) Average() int {
    return a.Sum() / 2
}

现在我们继续实施

component/impl1/impl.go // 为impl2假设类似的东西

package impl1

type ComponentImpl1 struct {
    base.AbstractComponent
}

func (c *ComponentImpl1) A() int {
    return 2
}

func (c *ComponentImpl1) A() int {
    return 4
}

// Here is how we would build this component
func New() *ComponentImpl1 {
    impl1 := &ComponentImpl1{}
    abs:=&base.AbstractComponent{
        IAbstractComponentsMember: impl1,
    }
    impl1.AbstractComponent = abs
    return impl1
}

我们为此使用单独的接口而不是使用相同的 IComponent 接口的原因是因为如果我们在这种情况下使用相同的接口,如果我们在impl* 中导入基本包以使用抽象“类”,并且我们还导入了impl*包在components包中,所以工厂可以注册它们,我们会找到一个循环引用。

所以我们可以有一个这样的工厂实现

组件/工厂.go

package component

// Default component implementation to use
const defaultName = "impl1"
var instance *Factory

type Factory struct {
    // Map of constructors for the components
    ctors map[string]func() IComponent
}

func (f *factory) New() IComponent {
    ret, _ := f.Create(defaultName)
    return ret
}

func (f *factory) Create(name string) (IComponent, error) {
    ctor, ok := f.ctors[name]
    if !ok {
        return nil, errors.New("component not found")
    }
    return ctor(), nil
}

func (f *factory) Register(name string, constructor func() IComponent) {
    f.ctors[name] = constructor
}

func Factory() *Factory {
    if instance == nil {
        instance = &factory{ctors: map[string]func() IComponent{}}
    }
    return instance
}

// Here we register the implementations in the factory
func init() {
    Factory().Register("impl1", func() IComponent { return impl1.New() })
    Factory().Register("impl2", func() IComponent { return impl2.New() })
}

Go 的面向对象概念来自 Small Talk,而不是像 C++ 那样的 Simula,也不是从 C++ 获得其面向对象概念的 Java。 记住这一点,Go 会突然变得清晰明了。

因此,Go 中没有类的概念。 只是对象,发送和接收消息。 Go 的接口可以从概念上解释为消息的集合。

Go 类型不“实现”接口,它们只是实现作为某些接口一部分的消息。

重复:没有类,没有抽象基类,因此在 Go 中没有“基于类的设计”(就像在 Small Talk 中一样)。

难怪试图在 Go 中实现 ABC 是一团糟,正如我们在这里清楚地看到的。

除非您从 method1 中删除 static 关键字,否则您所询问的示例不会在 Java 中编译,因此 Java 中正确的抽象类会像这样。

public abstract class A {
    void method1(){
    method2();}
    abstract void  method2();
}

要在 go-lang 中提供等效项,您必须按以下方式使用接口: Go Playground

package main

import (
    "fmt"
)

type AI interface {
    method2()
}

type A struct {
    AI
}

func (a * A) method1() {
   a.method2()
}

type B struct {
    *A
}
func (b *B) method2() {
   fmt.Print("Hello from B method1\n")
}

func NewB() *B{
   b := &B{}
   a := &A{b}
   b.A = a
   return b 
}

type C struct {
    *A
}

func (c *C) method2() {
    fmt.Print("Hello from C method1\n")
}

func NewC() *C{
    c := &C{}
    a := &A{c}
    c.A = a
    return c    
}

func main() {

     b := NewB()
     b.method1()

    c:= NewC()
    c.method1()
}

由于这仍然不容易如何将 java 抽象类/多继承转换/实现到 go-lang 这里是具有全面详细信息的帖子。 golang中的抽象类

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM