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

googlego中抽象类/方法(Java)的等价性,java,interface,go,static-methods,abstract,Java,Interface,Go,Static Methods,Abstract,我是新手,我想知道如何在Java中实现类似于抽象类和方法的结构。在Java中,我将执行以下操作: abstract class A{ static method1(){ ... method2(); ... } abstract method2(); } class B extends A{ method2(){ ... } } class C extends A{ method2(){ ... } } 我了解接口和结构。我可以构建一个接口,

我是新手,我想知道如何在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。难道没有其他方法吗

注意:当然,在我的例子中,这不仅仅是一种方法。另外,我有一个抽象类的层次结构,不想把所有的东西都下放到“子类”中


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

您可以使用复合接口,例如从软件包:


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

由于go没有OOP意义上的
静态方法,您经常会看到这些类型的方法被实现为包级函数:

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

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

public abstract class A {
    void method1(){
    method2();}
    abstract void  method2();
}
要在go lang中提供等效的接口,您必须以以下方式使用接口:


由于这仍然不容易,因此如何翻译/实现java抽象类/多重继承到go-lang,这里是一篇包含全面细节的文章

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

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

component
  base
    types.go
    abstract.go
  impl1
    impl.go
  impl2
    impl.go
  types.go
  factory.go
定义组件的定义,在本例中,将在此处定义:

组件/类型。转到

package component

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

type IAbstractComponentMembers {
    A() int
    B() int
}
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
}
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() })
}
现在让我们假设我们想要创建一个抽象类,它只实现SumAverage,但是在这个抽象实现中,我们希望能够使用已实现的AB返回的值

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

组件/基础/类型。转到

package component

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

type IAbstractComponentMembers {
    A() int
    B() int
}
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
}
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() })
}
然后我们可以继续实现抽象的“类”

组件/基础/抽象。转到

package component

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

type IAbstractComponentMembers {
    A() int
    B() int
}
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
}
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() })
}
现在我们开始实现

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*中导入base包以使用抽象的“类”我们还将impl*包导入组件包中,以便工厂可以注册它们,我们将找到循环引用

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

组件/工厂。转到

package component

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

type IAbstractComponentMembers {
    A() int
    B() int
}
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
}
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从面向对象的概念中获取闲聊,而不是像C++那样的模拟语言,而不是从C++获得它的面向对象概念的java。记住这一点,Go会突然变得清晰和明显

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

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

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


难怪我们在这里清楚地看到,在围棋中尝试实施ABC是一团混乱。

谢谢。让我看看我是否理解正确。你的意思是我应该为method1创建一个接口,为method2创建一个接口和一个复合接口。但是,对于使用method2的method1,我应该将我的实现放在哪里(可能我没有说得足够清楚)?这样我仍然会有重复的代码,对吗?我不太清楚我是否理解你,但是如果一个结构可以满足多个接口,或者你可以定义在
interfaceA
interfaceB
上做事情的函数,并将你的结构传递给它们,而不是在结构本身上实现代码。像这个答案一样,我想添加,如果您需要像抽象类一样具有结构接口,那么您可以使用@ANisus编写的相同原理,但添加getter方法。因此,您可以调用结构参数,如
Model.getName
where
Model
wouldbean解析您创建的某些接口的确切结构。IMO,这是一种非常复杂且令人困惑的嵌入滥用。我决不会让这段代码通过代码审查。此外,这些注释非常容易引起误解,没有“继承”或“抽象”,这些注释隐藏并混淆了Go embedding正在做什么。@Dave C-不反对这有点复杂,虽然我说这提出了更好的建议,但我希望看到抽象类实现的简单方法。总而言之,如果您不需要类似抽象类的功能,请不要使用呈现模式。忘记尝试用语言X实现某件事,就像用语言Y实现一样。这种方式通常会导致难以读/写/调试意大利面代码。Go没有类,当你在Go中设计时,不要再考虑类了。@DaveC你是在逆向思考。如果一个程序员熟悉某个模式,那么尝试去寻找对应的模式是很自然的