猿问

如何从吹 Java 代码生成 Go 代码?

我想写一个Java2Go生成器,但是我发现很难表达多态性(例如:形式arg是Base类,而真正的arg是Sub类),我如何在Go中表达吹代码?


class Base{

    public int i;     

  }


class Sub extends Base{ 

  }


class Test{

   public static int test(Base base){

          base.i = 99;

          return base.i;

   }

   public static void main(String [] args){

       Sub sub = new Sub();

       System.out.println(test(sub));

   }

}


RISEBY
浏览 283回答 3
3回答

扬帆大鱼

您需要复制代码或制作调用通用实用程序函数的包装器,这基本上是疯狂的。没有优雅的方法来执行“逐个函数翻译”。优雅的方法是用不同的方式编写程序。Go 程序从根本上必须具有不同的结构。从多年编写面向对象的代码开始,这是一个很难改变的习惯,但是当我找到解决问题的“类似 Go”的方法时,随着时间的推移,它通常会变得更简单。拥有适当的继承和所有似乎可以节省代码并保持整洁的东西,但是 - 至少以我的经验 - 经过多年的开发,它很容易像一团糟一样结束,或者至少很难深入挖掘,如果你还没有使用了一段时间的代码。Go 的接口有更多的限制,但它会迫使你让事情变得更简单和更“明显”。不同类之间的分离是明确的。也有一些优点;在您获得一些经验之后,“混合”类型比使用继承容易得多。例如,另一个“技巧”是一种类型可以满足多个接口。如果您一直在编写面向对象的代码,那么需要一些练习来习惯新工具。我建议不要编写翻译器,而是尝试编写一些基于 Go 的工具。那一定会很好玩。:-)

婷婷同学_

如果您的类中只有成员变量,那么您可以使用嵌入。但是,此解决方案不会扩展到您还需要类上的方法的情况,这些方法可以在子类中覆盖,因为名称冲突会阻止您的 Go 代码编译。您可以使用 vtable 将类编译为原始内存结构(就像编译为汇编程序或 C 一样),但是您必须实现自己的垃圾收集器。假设这不是您想要的,您可以扩展 vtable 的想法以包含返回成员变量地址的方法,这将允许您使用 Go 接口作为实现 vtable 的廉价方式。这是一些代码,稍微压缩以减少样板的外观。package mainimport "fmt"type Base struct {    i int}func (b *Base) get_i() *int { return &b.i }func NewBase() *Base { return &Base{} }type Sub struct {    parent Base}func NewSub() *Sub { return &Sub{*NewBase()} }func (s *Sub) get_i() *int { return s.parent.get_i() }type BaseI interface {    get_i() *int}func test(b BaseI) int {    *b.get_i() = 99    return *b.get_i()}func main() {    s := NewSub()    fmt.Println(test(s))}方法需要进行名称修饰,因为 Java 允许重载。根据对象的类型和所有方法参数的类型,您会发现在给定的调用站点上确切地确定需要调用哪个方法很有趣:)事实上,很多事情最终都需要改名。例如,上面的代码直接翻译了类名“Base”和“Sub”,但是如果我将其中一个类称为“main”,或者我将其称为“Sub”、“NewBase”(没有“ t 出现在原始 Java 源代码中,但在翻译过程中出现)?通常,翻译后的代码看起来更像这样,以避免出现这些类型的问题:type Java_class_Base struct {    Java_member_i Java_basetype_int}还有很多其他障碍。例如,上面的代码将 Java 转换int为 Go int,但两者并不相同。Go 的int32更接近,但行为仍然不同(例如,Java 指定了溢出时会发生什么,但 Go 没有)。这意味着即使是简单的表达式 likex = x + 1也很难翻译,因为您将不得不编写自己的 add 函数以确保翻译后的代码与 Java 代码的行为相同。另一个例子是每个对象都可能充当线程可重入锁(因为它可以synchronised打开)。这意味着您将不得不决定如何翻译它,这将涉及到 Java 线程的概念,并能够确定您的翻译调用正在哪个 Java 线程上执行。祝你好运!前面有很多困难,但制作编译器是一个有趣的挑战。
随时随地看视频慕课网APP

相关分类

Go
我要回答