【问题标题】:How do I translate this Java interface & inheritence structure to Golang? [closed]如何将这个 Java 接口和继承结构翻译成 Golang? [关闭]
【发布时间】:2018-06-15 05:37:07
【问题描述】:

是否可以将这种使用接口和继承的 Java 结构重写为惯用的 Golang 方式?

这不是超级复杂的Java代码,但它显示了类继承的力量,但我想尝试在Go中以某种方式达到同样的结果

Java 代码:

首先有一个类接口。

public interface WebEntry {
    String perform(ConnectionData connectionData, SessionData sessionData) throws Exception;
}

某处有一个网络条目列表WebEntry

List<WebEntry> webEntries = new ArrayList<>();
webEntries.add( new SavePasswordWebEntry() );

实现WebEntry的抽象类UserLoggedInWebEntry

public abstract class UserLoggedInWebEntry implements WebEntry {

    @Override
    public String perform(ConnectionData connectionData, SessionData sessionData) throws Exception {

        // THIS IS THE LOGIC I DO NOT WANT TO DUPLICATE, HENCE ITS USING CLASS INHERITANCE
        ...

        return userPerform(User user);

    }

    protected abstract String userPerform(User user) throws Exception;

}

通过使用类继承,我们可以创建一个UserLoggedInWebEntry,它的行为仍然与WebEntry 一样,但我们不需要在每次我们想要一个“用户登录网络条目”实例时重复... 逻辑:

public class SavePasswordWebEntry extends UserLoggedInWebEntry {

    @Override
    protected String userPerform(User user) throws Exception {
       ...
    }

}

所以重点是,由于它使用类继承,开发人员只需要实现String userPerform(User user),而无需在UserLoggedInWebEntry中复制...的逻辑。

这甚至可以在 Golang 中实现吗?如果有,会是什么样子?

【问题讨论】:

  • 重建什么?像任何 Java 代码一样乱七八糟?是的,你也可以在 Go 中做一些愚蠢的事情。关于 Go 代码的实际问题是什么?
  • 就像我在问题中所说的那样:> 但是,通过创建一个抽象类 UserLoggedInWebEntry,开发人员可以轻松创建仅实现具有签名保护的 String userPerform(User user) 的方法的 Web 条目,而无需复制UserLoggedInWebEntry.perform(...) 中的 ... 逻辑。通过这里使用类继承,开发不需要重复发生在UserLoggedInWebEntry 中的“...”逻辑
  • 这是我的问题。我如何在 Golang 中实现同样的目标?这甚至可能吗?如果是这样,如何
  • “刚学 Go”——这就是……我正在尝试……通过在 Stackoveflow 上提出这个问题来做。如果我知道 Go 正确以及如何实现相同的目标,我就不会在这里问它。
  • 主要建议是:停止在 Go 中重新创建 Java 模式。你会伤害自己。把它留在后面。你做不到,你也不会成功。不要问“我如何在 Go 中做 Java 的模式 X”。抱歉,如果我不清楚。

标签: java inheritance go


【解决方案1】:

我想出了如何靠自己完成同样的事情,尽管我很喜欢我得到的“Just learn Go”答案。

通过创建一个包装函数userLoggedInWebEntry 来解决这个问题,它接受WebEntryUserLoggedIn 函数签名,但返回一个WebEntry 函数签名。

它实现了和上面的Java继承代码一样的东西,让开发者只实现一个func( user User ) string并且userLoggedInWebEntry中的逻辑不重复

https://play.golang.org/p/adrk46YFIl8

package main

import (
    "fmt"
)

type ConnectionData string
type SessionData string
type User string

type WebEntry func(connectionData ConnectionData, sessionData SessionData) string
type WebEntryUserLoggedIn func( user User ) string

func main() {
    var webentries []WebEntry
    webentries = append( webentries, userLoggedInWebEntry(SavePasswordWebEntry) )

    // Test the invocation
    fmt.Println( webentries[0]("ConnectionData", "SessionData") )
}


func userLoggedInWebEntry( webEntry WebEntryUserLoggedIn ) WebEntry {

    return func(connectionData ConnectionData, sessionData SessionData) string {
        // // THIS IS THE LOGIC I DO NOT WANT TO DUPLICATE, HENCE ITS USING CLASS INHERITANCE
        var user User = "John"
        return webEntry( user )
    } 

}


func SavePasswordWebEntry( user User ) string {
    return fmt.Sprintf("user is %s", user )
}

【讨论】:

    【解决方案2】:

    可能是这样的?

    type WebEntry interface {
        Perform() string
    }
    
    type SomeWebEntry struct {
    }
    
    func (_ *SomeWebEntry) Perform() string {
        return "SomeWebEntry"
    }
    
    type OtherWebEntry struct {
        SomeWebEntry
    }
    
    func (this *OtherWebEntry) OtherPerform() string {
        return this.Perform() + "OtherWebEntry"
    }
    
    func main() {
        webEntries := []WebEntry{&SomeWebEntry{},&OtherWebEntry{}}
        for _, v := range webEntries {
            fmt.Println(v.Perform())
        }
        fmt.Println("-")
        fmt.Println(webEntries[1].(*OtherWebEntry).OtherPerform())
    }
    

    您可以使用名为embedding 的功能。

    【讨论】:

      【解决方案3】:

      你看。不知道我理解对不对。

      package main
      
      import (
          "fmt"
      )
      
      type ConnectionData struct{}
      type SessionData struct{}
      
      type WebEntry interface {
          Perform(c ConnectionData, s SessionData) (string, error)
      }
      
      type UserLoggedInWebEntry struct {
      }
      
      func (u *UserLoggedInWebEntry) Perform(c ConnectionData, s SessionData) (string, error) {
          return u.UserPerform(c, s)
      }
      
      func (u *UserLoggedInWebEntry) UserPerform(c ConnectionData, s SessionData) (string, error) {
          return "UserLoggedInWebEntry UserPerform", nil
      }
      
      type SavePasswordWebEntry struct {
          UserLoggedInWebEntry
      }
      
      func (sp *SavePasswordWebEntry) Perform(c ConnectionData, s SessionData) (string, error) {
          return "SavePasswordWebEntry Perform", nil
      }
      
      func main() {
          webEntries := make([]WebEntry,0)
          webEntries = append(webEntries, new(SavePasswordWebEntry))
          for _, we := range webEntries {
              fmt.Println(we.Perform(ConnectionData{},SessionData{}))
          }
      }
      

      Playground

      【讨论】:

      • 不幸的是,这是不正确的,因为“SavePasswordWebEntry”应该接受“用户”——注意参数签名是如何变化的。在上述解决方案中,所有函数都接受“ConnectionData”和“SessionData”。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-14
      • 1970-01-01
      相关资源
      最近更新 更多