这是将 Java 接口转换为 Scala 的正确方法吗?

发布于 2024-12-29 10:49:21 字数 777 浏览 3 评论 0原文

我开始学习Scala,我会做一个简单的交叉编译器。

我将支持一小部分指令,例如打印。

注意:代码片段未经测试或编译。
这是我在 JAVA 中要做的事情。

public interface Compiler{
 String getPrintInstruction();
}

public class JavaCompiler implements Compiler{
 public String getPrintInstruction(){
  return "System.out.print(arg0);"
 }
}

public class ScalaCompiler implements Compiler{
 public String getPrintInstruction(){
  return "print(arg0);"
 }
}

下面的代码片段是正确的“Scala 方式”吗?

trait Compiler {
  var printInstruction: String
}
class JavaCompiler extends Compiler {
  var printInstruction = "System.out.print(arg0);"
}
class ScalaCompiler extends Compiler {
  var printInstruction = "print(arg0);"
}

编辑:

我会将第二个问题移至新线程。

I am starting to learn Scala and I will do a simple cross compiler.

I will support a small set of instructions like print.

Note: the code snippets are not tested or compiled.
Here is what I would do in JAVA.

public interface Compiler{
 String getPrintInstruction();
}

public class JavaCompiler implements Compiler{
 public String getPrintInstruction(){
  return "System.out.print(arg0);"
 }
}

public class ScalaCompiler implements Compiler{
 public String getPrintInstruction(){
  return "print(arg0);"
 }
}

Is the snippet below the correct "Scala way"?

trait Compiler {
  var printInstruction: String
}
class JavaCompiler extends Compiler {
  var printInstruction = "System.out.print(arg0);"
}
class ScalaCompiler extends Compiler {
  var printInstruction = "print(arg0);"
}

EDIT:

I will move my second question to a new thread.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情绪失控 2025-01-05 10:49:21

对于 1:1 映射,这些 var 应更改为 def

trait Compiler {
  def printInstruction: String
}

class JavaCompiler extends Compiler {
  def printInstruction = "System.out.print(arg0);"
}

class ScalaCompiler extends Compiler {
  def printInstruction = "print(arg0);"
}

def 声明一个方法。当你不提供实现时,它就变成了抽象方法。

编辑:

这里使用的技术是一种有效且有用的技术。或者,您可以使用以下两种技术之一来模拟您的问题。

1)受歧视的工会。 (又名求和类型。)

请参阅

sealed trait Compiler {
  def printInstruction: String = this match {
    case JavaCompiler => "System.out.print(arg0);"
    case ScalaCompiler => "print(arg0);"
  }
}

case object JavaCompiler extends Compiler
case object ScalaCompiler extends Compiler

2)类型类模式。

这里是 Daniel Sobral 的精彩帖子这个话题。您可以通过谷歌搜索术语“类型类”、“模式”、“Scala”、“隐式”等来挖掘更多信息。如果问题是使用类型类模式建模的,那么您的代码可能如下所示:

trait Compiler[C] {
  def printInstruction(c: C): String
}

case object JavaCompiler

implicit object JavaCompilerIsCompiler extends Compiler[JavaCompiler.type] {
  def printInstruction(c: JavaCompiler.type): String = "System.out.print(arg0);"
}

case object ScalaCompiler

implicit object ScalaCompilerIsCompiler extends Compiler[ScalaCompiler.type] {
  def printInstruction(c: ScalaCompiler.type) = "print(arg0);"
}

对于您的问题,原始方法和可区分联合方法似乎是最好的建模解决方案。

For a 1:1 mapping, those vars should be changed to defs.

trait Compiler {
  def printInstruction: String
}

class JavaCompiler extends Compiler {
  def printInstruction = "System.out.print(arg0);"
}

class ScalaCompiler extends Compiler {
  def printInstruction = "print(arg0);"
}

def declares a method. When you don't provide an implementation, it becomes an abstract method.

EDIT:

The technique used here is a valid and useful technique. Alternatively you could use one of the following two techniques to model your problem.

1) Discriminated unions. (aka sum types.)

Refer to this excellent article to learn about this concept. This is how your example would probably look like when modeled this way:

sealed trait Compiler {
  def printInstruction: String = this match {
    case JavaCompiler => "System.out.print(arg0);"
    case ScalaCompiler => "print(arg0);"
  }
}

case object JavaCompiler extends Compiler
case object ScalaCompiler extends Compiler

2) Type class pattern.

Here is a great post by Daniel Sobral on this topic. You can dig up a few more by googling the terms type-class, pattern, Scala, implicits etc. This is how your code might look like if the problem's modeled with type class pattern:

trait Compiler[C] {
  def printInstruction(c: C): String
}

case object JavaCompiler

implicit object JavaCompilerIsCompiler extends Compiler[JavaCompiler.type] {
  def printInstruction(c: JavaCompiler.type): String = "System.out.print(arg0);"
}

case object ScalaCompiler

implicit object ScalaCompilerIsCompiler extends Compiler[ScalaCompiler.type] {
  def printInstruction(c: ScalaCompiler.type) = "print(arg0);"
}

For your problem, the original approach and the discriminated unions approach seem to be the best modeling solutions.

带刺的爱情 2025-01-05 10:49:21

当我在特征中声明变量时,为什么我必须在类中再次重新声明该变量?

因为您声明了方法 printInstruction 的签名,但您这样做了不说它做了什么。在中,因为它不是一个抽象类,所以应该定义所有函数。
顺便说一句,如果您希望在每个实现中都执行相同的操作,则可以直接在 Trait Compiler 中定义 printInstruction 。

Why do I have to re declare the variable one more time in the class when I have declared it in the trait?

Because you declared the signature of the method printInstruction but you did not say what it did. In a class, as it is not an abstract class all functions should be defined.
By the way, you could have defined printInstruction directly in the trait Compilerif it is supposed to do the same in every implementation.

情场扛把子 2025-01-05 10:49:21

最惯用的方法是使用 def 表示抽象属性,使用 val 表示具体的只读属性。在统一访问原则下,val可用于实现方法:

trait Compiler {
  def printInstruction: String
}

class JavaCompiler extends Compiler {
  val printInstruction = "System.out.print(arg0);"
}

class ScalaCompiler extends Compiler {
  val printInstruction = "print(arg0);"
}

The most idiomatic way is to use a def for abstract properties, and a val for concrete read-only properties. Under the Uniform Access Principle, a val can be used to implement a method:

trait Compiler {
  def printInstruction: String
}

class JavaCompiler extends Compiler {
  val printInstruction = "System.out.print(arg0);"
}

class ScalaCompiler extends Compiler {
  val printInstruction = "print(arg0);"
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文