Scala 抽象类

3

我是scala的新手,不确定如何调用抽象类来创建所需的对象。希望能得到帮助。

abstract class Expr{
    case class Number(n:Double) extends Expr
    case class Sum(e1:Expr, e2: Expr) extends Expr
    case class Subtract(e1: Expr, e2: Expr) extends Expr
    case class Divide(e1: Expr, e2: Expr) extends Expr
    case class Abs(e1: Expr) extends Expr
    case class Mod(e1: Expr, e2: Expr) extends Expr
    def eval(e:Expr): Double = e match{
        case Number(n) => n;
        case Sum(e1,e2) => eval(e1) + eval(e2);
    }
}
object main{
    def main(args: Array[String])  {
        val e = Expr();
        println("hello");
    }
}

我希望能够创建Expr对象并使用eval函数。

谢谢。

1
这看起来像是作业。你具体有什么问题? - Samuel Tardieu
4个回答

8
您可以通过添加 {} 来实例化 Expr,以表示一个空的类体。因此,如果您编写了以下代码,则代码将起作用:
val e = Expr() {};
val n = e.Number(1.0);
val sum = e.Sum(n, n);
println(e.eval(sum));

但我不明白为什么 case classes 必须在 Expr 类中。为什么不写成:

abstract class Expr {}

object Eval {
  def apply(e : Expr) = e match{
    case Number(n) => n;
    case Sum(e1,e2) => Eval(e1) + Eval(e2);
  }
}

case class Sum(e1 : Expr, e2 : Expr) extends Expr

然后你可以更优雅地引用它们:
Eval(Sum(Number(1), Number(1)))

4

那么这个怎么样:

abstract class Expr {
  def eval: Double
}
case class Number(n:Double) extends Expr {
  def eval = n
}
case class Sum(e1:Expr, e2: Expr) extends Expr {
  def eval = e1.eval + e2.eval
}
case class Subtract(e1: Expr, e2: Expr) extends Expr {
  def eval = e1.eval - e2.eval
}

object Eval {
  def apply(e : Expr) = e.eval
}

1

[更新]

顺便说一下,我更喜欢@JensEgholm的Eval对象(带有apply方法),而不是我的建议将eval添加到主函数中。我的观点是,您的eval代码应该是Scala对象的一部分,以便轻松访问,而不是任何Scala抽象类的一部分。

[原文]

那看起来像是Odersky的《Scala编程》中的示例/模板代码(顺便说一句,我强烈推荐这本书)

如果是这样,那么您复制模板时出现了错误。在abstract class Expr之后没有大括号。这一行是完整的抽象类声明。此外,eval方法应该放在您的主对象中。请尝试以下内容:

abstract class Expr
case class Number(n:Double) extends Expr
case class Sum(e1:Expr, e2: Expr) extends Expr
case class Subtract(e1: Expr, e2: Expr) extends Expr
case class Divide(e1: Expr, e2: Expr) extends Expr
case class Abs(e1: Expr) extends Expr
case class Mod(e1: Expr, e2: Expr) extends Expr

object main{
  def eval(e:Expr): Double = e match{
      case Number(n) => n;
      case Sum(e1,e2) => eval(e1) + eval(e2);
  }
    def main(args: Array[String])  {
      val n = Number(1.0);
      val m = Number(2.0);
        println(eval(Sum(n,m)));
    }
}

该程序应该打印出“3.0”。

1
根据Odersky的说法,如果你是Scala的新手,除非你知道为什么要使用抽象类,否则大多数情况下应该使用traits。 使用抽象类的优势是什么? 上述示例可以使用traits合法,并且可以一起“混合”。
scala> trait Expr
defined trait Expr

scala> case class Number(n:Double) extends Expr
defined class Number

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接