没有实例

时间:2017-06-15 14:34:12

标签: scala scope static

我刚开始学习Scala并且正在关注this tutorial。它们实现了Tree结构,如下面的代码所示,以创建数学公式。他们在中途将type关键字引入

type Environment = String => Int

以便所有变量都可以映射到数字。

我的问题是,如何在没有Tree实例的情况下引用该类型?即如何将类型Environment定义为 static

示例代码:

package com.company

/**
  * The tree class which represents a formula
  */
abstract class Tree {
    /**
      * The type to map a variable to a value
      */
    type Environment = String => Int

    /**
      * Using the given Environment, it evaluates this tree
      * @param env The environment which maps variables to values
      * @return The result of the fomula
      */
    def eval(env: Environment): Int = this match {
        case Sum(lhs, rhs) => lhs.eval(env) + rhs.eval(env)
        case Variable(v)   => env(v)
        case Constant(c)   => c
    }
}

/**
  * Represents a sum between to values
  * @param lhs Left hand value
  * @param rhs Right hand value
  */
case class Sum(lhs: Tree, rhs: Tree) extends Tree

/**
  * Represents an unknown and named value or named variable
  * @param variable The name of the variable
  */
case class Variable(variable: String) extends Tree

/**
  * An unnamed constant value
  * @param value The value of this constant
  */
case class Constant(value: Int) extends Tree

/**
  * Base class for this program
  */
object Tree {
    /**
      * Entry point of the application
      * @param args
      */
    def main(args: Array[String]) {
        //Define a tree: (x + 3) + 2
        val tree: Tree = Sum(Sum(Variable("x"), Constant(3)), Constant(2))
        //Define an environment: x=5 and y=6
        val env: tree.Environment = {case "x" => 5; case "y" => 6}
        //       ^ Refers to the object tree rather than the class Tree
        //val env: Tree.Environment = {case "x" => 5; case "y" => 6}
        //  ^ Results in the error: Error:(55, 27) type Environment is not a member of object com.company.Tree

        println(tree) //show the tree
        println(s"x=${env.apply("x")} | y=${env.apply("y")}") //show values of x and y
        println(tree.eval(env)) //evaluates the tree
    }
}

2 个答案:

答案 0 :(得分:1)

使用#(类型投影)访问类型成员而不引用实例:

 val env: Tree#Environment = {case "x" => 5; case "y" => 6}

此处提供了更多说明:What does the `#` operator mean in Scala?

P.S。实际上你不能完全理解你的类型“静态” - 也就是静态成员,因为JVM实际上“忘记”了这些类型(擦除),所以tree.EnvironmentTree.Environment(令人惊讶)由编译器处理,而不是在运行时。即使object Tree{ type Environment = ... }意味着你的类型将成为单例对象Tree的成员(因此Tree仍然会有一个引用)

答案 1 :(得分:1)

在Scala类型中,就像其他所有类型一样,可以通过将它们放在对象中来使其成为“静态”。

abstract class Tree
object Tree {
  type Environment = String => Int
}

我说“静态”,因为Scala(语言)没有像其他编程语言那样的静态概念。