我刚开始学习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
}
}
答案 0 :(得分:1)
使用#
(类型投影)访问类型成员而不引用实例:
val env: Tree#Environment = {case "x" => 5; case "y" => 6}
此处提供了更多说明:What does the `#` operator mean in Scala?
P.S。实际上你不能完全理解你的类型“静态” - 也就是静态成员,因为JVM实际上“忘记”了这些类型(擦除),所以tree.Environment
和Tree.Environment
(令人惊讶)由编译器处理,而不是在运行时。即使object Tree{ type Environment = ... }
意味着你的类型将成为单例对象Tree的成员(因此Tree仍然会有一个引用)
答案 1 :(得分:1)
在Scala类型中,就像其他所有类型一样,可以通过将它们放在对象中来使其成为“静态”。
abstract class Tree
object Tree {
type Environment = String => Int
}
我说“静态”,因为Scala(语言)没有像其他编程语言那样的静态概念。