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

I am new to Go and I'm wondering how I can implement a structure similar to abstract classes & methods in Java. In Java, I'd do the following:

abstract class A{

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

 abstract method2();

}

class B extends A{

 method2(){
  ...
 }

}

class C extends A{

 method2(){
  ...
 }

}

I know about interfaces and structs. I could build an interface and then a struct to implement method1. But what about method2? I know that I can embed one interface in another and also a struct as a field of another struct. But I don't see a way to implement my structure with those methods.

The only solution I see is to implement method1 both in class B and class C. Isn't there another way?

Note: of course in my case it's not just one method. Also I've got a hierarchy of abstract classes and don't really want to move everything down to the 'subclasses'.

The examples I've found on the internet are mostly with only one method per interface. It would be great if one of you guys could give me a hint here! Thanks.

Since Go does not have static methods in the OOP sense, you often see those types of methods being implemented as package level functions:

package mypackage

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

Such package level functions would then take an interface as an argument. Your code would in that case look something like this:

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)    
}

Output:

StructB

You can have composite interfaces, for example from the io package :

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
}

As a side note, don't try to implement java code using go, try to learn the Go Way.

The example you are asking would not compile in Java unless you remove static keyword from method1, so the correct abstract class in Java would like like this.

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

To provide equivalent in go-lang you would have to use an interface in the following way: Go Playground

package main

import (
    "fmt"
)

type AI interface {
    //define all methods that you want to override
    method2()
}

type A struct {//this type is an abstract of AI type since it does not implement method2
    AI
}

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

type B struct {//inherit all from A
    *A
}
func (b *B) method2() {
   fmt.Print("Hello from B method1
")
}

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

type C struct {//inherit all from A
    *A
}

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

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

func main() {

     b := NewB()
     b.method1()

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

Since this still not may be easy how to translate/implement java abstract classes/multi-inheritance to go-lang here is the post with comprehensive details. Abstract Class in golang

This is the way I achieved implementing an abstract class the easy way avoiding to run into cyclic references and maintaining good factory patterns.

Let us assume we have the following package structure for our component

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

Define the definition of the component, in this example it will be defined here:

component/types.go

package component

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

Now let's assume we want to create an abstract class that implements Sum and Average only, but in this abstract implementation we would like to have access to use the values returned by the implemented A and B

To achieve this, we should define another interface for the abstract members of the abstract implementation

component/base/types.go

package base

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

And then we can proceed to implement the abstract "class"

component/base/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
}

And now we proceed to the implementations

component/impl1/impl.go // Asume something similar for 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
}

The reason we use a separate interface for this instead of using the same IComponent interface, is because if we use the same interface in this case, if we import the base package in impl* to use the abstract "class" and also we import the impl* packages in the components package, so the factory can register them, we'll find a circular reference.

So we could have a factory implementation like this

component/factory.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 LANG OO inherits from Small Talk, not Simula like C++ and not from Java which inherits OO concepts from C++. Remember this and GO OO will sudenly become clear and obvious.

Thus. There is no concept of class in GO. Just objects, sending and receiving messages. GO interface can be conceptually explained as collection of messages.

GO types do not “implement” interfaces they just implement messages that are part of some interface.

Repeat: there is no class, no abstract base class and thus there is no “class based design” in Go (as in Small Talk).

No wonder trying to implement ABC in GO is a mess, as we see here clearly.