2017-06-15 16 views
0

私はちょうどスカラを学び始めていて、this tutorialに従っていました。彼らはTree構造を実装しています。下のコードは、数式を作成するためのコードです。彼らはインスタンスなしでクラス `type`を参照

type Environment = String => Int 

としてtypeキーワードを紹介する途中で、すべての変数が数字にマッピングすることができるように。

私の質問は、Treeのインスタンスを持たないタイプをどのように参照しますか?私。タイプEnvironmentというスタティックと定義するにはどうすればよいですか。


例コード:

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 
    } 
} 

答えて

1

使用インスタンスを参照することなく、型メンバにアクセスする#(型の投影):

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

ここで提供される詳細な説明:What does the `#` operator mean in Scala?

PS JVMは実際にはそのような型(消去)について「忘れる」ので、実際にはあなたの型を静的なメンバという意味で静的にすることはできないので、実行時ではなくtree.EnvironmentTree.Environment(驚くべきことに)が処理されます。 Even object Tree{ type Environment = ... }は、あなたの型がシングルトンオブジェクトTreeのメンバになることを意味します(したがって、Treeはまだ参照を持ちます)

+0

なぜ '.'演算子で' Environment'を参照すればいいのですか? 'val Tree:Tree'は可能なので私は推測しますか? – Didii

+0

@Didiiそれは構文です。 '.'はいくつかの参照(シングルトン)からメンバーにアクセスすることを意図しています。 '#'はそのようなものを必要としません。 [Type Projection](https://www.scala-lang.org/files/archive/spec/2.11/03-types.html)を参照してください。 – dk14

+0

@Didii 'val Tree:Tree'は実際には大きな問題ではありません言葉 - それは読みやすさと美的感情を傷つけるだけである。その理由は、 'val Tree'が' class tree'を単に "シャドー"することができるからです(局所的な値が外側のスコープの他の値を遮るかもしれません) - スカラではよくあることです。 – dk14

1

Scala型では、他のすべてと同様に、オブジェクト内に配置することによって "静的"にすることができます。

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

「静的」と言います。これは、Scala(言語)には他のプログラミング言語のように静的な概念がないためです。

関連する問題