2017-05-24 6 views
0

でJavaから輸入不変「ヴァル」を使用:私は私の混乱を表示するにはScalaで、次の例を使用していScalaの

import java.util.HashMap 
val jhm = new HashMap[String, Int] 
jhm.put("myId", 1) 
jhm.put("yourId", 2) 

そして、それは私がこれを行う場合は今すぐ「JHM」に

を追加することができますScalaで:

val nmap = Map() 
nmap += ("myId" -> 1) 

これは期待できません。私の質問:最初のケースで不変の「val」を変更できるのはなぜですか?

+1

putは、jhmの参照を変更するのではなく、値を追加することです.2番目のインスタンスでは、不変のマップを作成してからputを実行し、nmapのインスタンスを変更します。 – SMA

答えて

4

valは、不変参照を作成します。つまり、このvalは常に同じオブジェクトを指します。オブジェクト自体が独自の状態を変更しないことを保証するものではありません。

3

put()をHashMapにマップすると、新しい参照が返されません。 2番目のケースでは、不変のマップに値を追加しているので、新しいマップが返されます。あなたのJavaの例に相当するScalaは、次のようになるでしょう:

import collection.mutable.Map 

val nmap = Map()[String, Int] 
nmap += ("a" -> 1) 
+0

しかし、スカラコードがJavaクラスのオブジェクトのときには 'val'を変更する必要がありますが、純粋なScalaタイプの場合は変更できません。 – NKM

+0

@NKM valは、オブジェクト自体が変更できないことを意味するものではありません。参照が変更できないことを意味します。 Java HashMapでは、可変オブジェクトを変更していますが、そのオブジェクトへの参照は同じオブジェクトを指しています。 Scala不変のマップでは、キーの値のペアを追加すると新しいマップが返されるため、参照が変更されます。 – sheunis

+0

@NKM: 'val'は変更されません。 'val'によって参照されるオブジェクトはそうです。 –

0

あなたは不変性の2つの異なる '用法'を混ぜています。

何かに対して可変(var)または不変(val)参照を持つことができ、何かを変更可能または不変にすることができます。

例:

var x = 3 
x = 4 // it works, `x` can be reassigned 

val y = 3 
y = 4 // it fails, `y` can't be reassigned 

その '何か' は、参照は」内部状態を持っているときに問題があります。 IntまたはStringのようなプリミティブ型にはこの問題はありませんが、どのクラスでも使用できます。スカラコレクションは、mutable collectionsimmutable collectionsがあるため、新しいスカラープログラマーにとって共通の痛みです。

違いは、不変なコレクションの操作では新しいコレクションが返されますが、元のものはそのまま残り、変更可能なコレクションではコレクション自体が変更されるという点です。

ご使用のスカラーMapは不変のマップであり、そのようなメソッドはありません。 myMap ++ (key -> value)を実行して、新しいマップを取得することができます。

オブジェクトの可変性/状態を持つ参照で可変性を混在させると、より大きな混乱が生じます。あなたはどんな疑問が私/私たちに知らせている場合

val x1 = scala.collection.mutable.ListBuffer(1,2,3) // immutable reference to mutable object 

// please, never use this in real code 
var x2 = scala.collection.mutable.ListBuffer(1,2,3) // mutable reference to mutable object 

// please, try to use this as much as possible 
val x3 = scala.collection.immutable.List(1,2,3) // immutable reference to immutable object 

var x4 = scala.collection.immutable.List(1,2,3) // mutable reference to immutable object 

ので、我々は

+0

私はそれを得ました。あなたの詳細な説明をありがとう。 – NKM

0

管理要約

を助けることができることをあなたが同等の起動されていません。あなたは、のようなものがで少し自分を果たすべき同等のクラスのメソッドmutable.Mapを使用し、+=put(...)に置き換えます。両方とも同じ動作をします。

詳細な回答

ここで起こって二つの異なる操作があります。最初の要素は、マップに要素を追加することです。put(...)のJavaマップは、put(...)スカラーでの操作と同等です。ではなく、+という新しいMapが作成されます。以下は、コンパイラによって完全に罰金です:

val map = Map[Int, Int]() 
map: scala.collection.mutable.Map[Int,Int] = Map() 

map.put(1, 2) 
res0: Option[Int] = None 

map 
res1: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2) 

キーと値のペアを置くことによって、mapはその状態を変異させます。これでエラーは発生しません。しかし、put(...)メソッドを呼び出すのではなく、+=メソッドを呼び出しています。

  • マップを変更しないput(...)ScalaDoc+ScalaDoc)とは対照的に可変
  • に結果を割り当てる

    1. コール+方法が、作成されます。これは、本質的に2つの操作手段immutable.Mapに似た新しいもの 新しいマップを作成した後、そのマップをvalに再割り当てしようとすると、コンパイラのエラーが発生します。

      同じ動作をJavaで目撃することができます。

      final int answer = 42; 
      answer = 23; 
      

      これはコンパイルエラーjava: cannot assign a value to final variable answerになります。

    関連する問題