以下是我如何使用Java接口构建实现一项功能的通用契约的示例:
package main.java;
public class Main {
interface Calculate {
public int run();
}
private class Calc1 implements Calculate {
@Override
public int run() {
return 1;
}
}
private class Calc2 implements Calculate {
@Override
public int run() {
return 0;
}
}
public static void main(String args[]){
Main m = new Main();
Calculate c = m.new Calc1();
System.out.println(c.run());
c = m.new Calc2();
System.out.println(c.run());
}
}
转到Scala特征是我如何重新实现上述相同的逻辑:
package main.scala
object traitsfun {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
trait Calc {
def run: Int
}
class Calc1 extends Calc {
override def run = 1
}
class Calc2 extends Calc {
override def run = 0
}
val c1 = new Calc1().run //> c1 : Int = 1
val c2 = new Calc2().run //> c2 : Int = 0
}
这是Scala特征的使用方式吗?
答案 0 :(得分:1)
是的,这是您可以在Scala中使用特征的一种方法。
但与Java不同,Scala特征也可以包含一些(可能是默认的)实现。
他们在Scala中是一个复杂的野兽;我建议仔细阅读它们的用法。
答案 1 :(得分:1)
这个例子对我来说似乎没问题。几句话:
1)如果你有不改变的特质成员,可以考虑将它们声明为lazy val
。 Lazy vals只被评估一次(第一次需要它们时),另一方面,def
s每次被调用时都会被评估。
2)如果您想阻止其他类继承您的特征,请考虑将其声明为sealed trait
。这意味着只接受在同一文件中声明的子类。
3)您不需要空括号来实例化Scala中的类。
4)Scala特性与Java接口最重要的区别在于它们也可以包含方法的实现,而不仅仅是声明它们。 (再次问好,多重继承:))考虑到这一切,我们可以通过以下方式重写您的特定示例:
package main.scala
object traitsfun {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
sealed trait Calc {
lazy val run: Int = 0 // val should have a default value
def standardMethod(param:String) = println(s"Hello $param")
}
class Calc1 extends Calc {
override lazy val run = 1
}
class Calc2 extends Calc {
override lazy val run = 0
}
val c1 = (new Calc1).run //> c1 : Int = 1
val c2 = (new Calc2).run //> c2 : Int = 0
(new Calc1).standardMethod("Calc1") //> "Hello Calc1"
}
(当然,所有这些只是用非常基本的例子来表达:))