2012-01-27 93 views
1

我开始学习Scala,我会做一个简单的交叉编译器。这是将Java接口转换为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);" 
} 
} 

低于正确“斯卡拉方式” 的片段?

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

编辑:

我将我的第二个问题转移到一个新的线程。

+0

你声明没有定义,直到你给它一个值的变量。尝试扩展编译器而不给printIntru提供一个值。它不是一个真正的重新声明,因为你可以看到,如果你给它一个非字符串值如42。 – thoredge 2012-01-27 12:47:57

+0

我不明白,请忍受我:),它似乎定义,因为如果我给它的值42编译器写:在trait类型为String的Compiler中重写变量printInstruction;变量printInstruction具有不兼容的类型 – Farmor 2012-01-27 13:37:10

+0

您的变量_definition_中出现错误,因为超类中的变量_declaration_具有不兼容的类型。我们声明了一个String类型的变量printInstruction,并且我们将该值的值定义为例如“hi”。与java相反,您不能忽略定义并获得默认值(null或0)。在这方面,'var x:String'是抽象的,就像一个方法是抽象的;然而这个词没有被使用,它是未定义的。 – thoredge 2012-01-27 13:52:03

回答

2

对于1:1映射,应将那些var s更改为def s。

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)歧视的工会。 (又名总和类型)

请参阅this excellent article了解此概念。这就是你的例子可能看起来像这样建模时的样子:

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是Daniel Sobral在这个话题上的一篇很棒的文章。您可以通过谷歌搜索挖出更多的一些条款类型类,模式,斯卡拉,implicits等,这是你的代码的外观一样,如果这个问题与类型的类模式为蓝本:

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

对于您的问题,原来的方法和受歧视的工会方法似乎是最好的建模解决方案。

+0

或者至少到'val'而不是'var'。 – Jesper 2012-01-27 12:36:31

+0

感谢您的答案,但我不想要1:1映射我想要最好的Scala方式来解决我的“问题”。我正在尝试学习Scala方法,而不是只使用Java思维的Scala语法。 – Farmor 2012-01-27 12:40:12

+0

@Farmor,这里使用的技术也在Scala中广泛使用。并非所有来自Java的技术都会因Java中的使用而过时。 – missingfaktor 2012-01-27 12:47:34

0

为什么我必须在课堂上再次声明变量一次?

因为您宣布了方法printInstruction的签名,但您没有说明它做了什么。在class中,因为它不是abstract class所以应该定义所有功能。 顺便说一下,如果应该在每个实现中执行相同的操作,则可以直接在trait Compiler中定义printInstruction

+0

也许我误解了Scala,但不是变量而不是方法?或者Scala将变量当作方法处理?对于每个编译器,printInstruction不应该是一个方法,而应该是一个字符串字段,其中字符串不同。 – Farmor 2012-01-27 12:43:50

+0

我认为你写了'getPrintInstruction()'是误导了我们,括号是你写了一个方法的标志(在java中它是一个方法)。因此,变量与函数不同,因为您可以设置和获取变量,基本上不能设置函数,您可以使用它来“创建”结果。 – 2012-01-27 12:47:51

1

最习惯的方法是对抽象属性使用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);" 
} 
相关问题