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

db2dz4w8  于 2023-03-10  发布在  Go
关注(0)|答案(6)|浏览(334)

我是Go语言的新手,我想知道如何在Java中实现一个类似于抽象类和方法的结构。在Java中,我会这样做:

abstract class A{

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

 abstract method2();

}

class B extends A{

 method2(){
  ...
 }

}

class C extends A{

 method2(){
  ...
 }

}

我知道接口和结构体。我可以构建一个接口,然后构建一个结构体来实现方法1。但是方法2呢?我知道我可以将一个接口嵌入到另一个接口中,也可以将一个结构体作为另一个结构体的字段。但是我看不到用这些方法实现我的结构体的方法。
我看到的唯一解决方案是在类B和类C中都实现method 1。没有其他方法吗?
注意:当然,在我的例子中,它不仅仅是一个方法,而且我有一个抽象类的层次结构,并不真的想把所有的东西都移到“子类”中。
我在网上找到的例子大多数都是每个接口只有一个方法。如果你们能给予我一个提示就太好了!谢谢。

9fkzdhlc

9fkzdhlc1#

您可以拥有复合接口,例如来自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

uubf1zoe

uubf1zoe2#

由于Go语言没有面向对象的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
lf5gs5x2

lf5gs5x23#

这就是我实现抽象类的方法--避免遇到循环引用和维护良好工厂模式的简单方法。
让我们假设组件具有以下包结构

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

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

组件/类型.go

package component

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

现在假设我们想创建一个抽象类,它只实现SumAverage,但是在这个抽象实现中,我们希望能够使用由所实现的AB返回的值
要实现这一点,我们应该为抽象实现的抽象成员定义另一个接口

组件/基础/类型.go

package base

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

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

组件/基础/抽象.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
}

现在,我们继续进行实现

组件/impl 1/impl.go//对impl 2取类似值

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中导入base包来使用抽象“类”,并且我们在components包中导入impl包,这样工厂就可以注册它们,我们会发现一个循环引用。
因此,我们可以有这样的工厂实现

组件/工厂.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() })
}
jecbmhm3

jecbmhm34#

Go语言的面向对象概念来自SmallTalk,而不是像C那样的Simula,也不是来自Java,Java的OO概念来自C,记住这一点,Go语言就会变得清晰明了。
因此,在Go语言中没有类的概念,只有对象,发送和接收消息。Go语言的接口在概念上可以解释为消息的集合。
Go语言类型并不“实现”接口,它们只是实现了作为某个接口一部分的消息。
重复一遍:Go语言中没有类,没有抽象基类,因此也就没有“基于类的设计”(如Small Talk)。
毫无疑问,在Go语言中实现ABC会是一团乱麻,这一点我们可以清楚地看到。

fae0ux8s

fae0ux8s5#

我使用这个技巧用常见的实现来实现一些sugar API:

package main

import (
        "fmt"
)

type Api interface {
        Sugar()
        Impl()
}

// Common sugar API implementation
type CommonSugar struct {
        BasicApi interface {
                Impl()
        }
}

func (s CommonSugar) Sugar() {
        fmt.Println("Calling Impl in Sugar")
        s.BasicApi.Impl()
        fmt.Println("Called Impl in Sugar\n")
}

// A implementation
type ImplA struct {
        CommonSugar
}

func (a *ImplA) Impl() {
        fmt.Println("A Impl")
}

func NewApiA() Api {
        impl := &ImplA{}
        impl.CommonSugar.BasicApi = impl
        return impl
}

// B implementation
type ImplB struct {
        CommonSugar
}

func (a *ImplB) Impl() {
        fmt.Println("B Impl")
}

func NewApiB() Api {
        impl := &ImplB{}
        impl.CommonSugar.BasicApi = impl
        return impl
}

func main() {
        api := NewApiA()
        api.Sugar()

        api = NewApiB()
        api.Sugar()
}

下面是程序输出:

Calling Impl in Sugar
A Impl
Called Impl in Sugar

Calling Impl in Sugar
B Impl
Called Impl in Sugar
bxjv4tth

bxjv4tth6#

除非从method 1中删除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,这里有一个详细的帖子。Abstract Class in golang

相关问题