0

これらの定義を考えると:

type HasMkString = { def mkString(sep:String):String }
val name = "John"
val names = List("Peter", "Gabriel")

そして、これらの事実を考えると:

name.mkString("-") // => "J-o-h-n"

name.isInstanceOf[HasMkString] // => true
names.isInstanceOf[HasMkString] // => true

これが機能している間:

names.asInstanceOf[HasMkString].mkString("-")
// => Peter-Gabriel

これは動作しません:

name.asInstanceOf[HasMkString].mkString("-")

java.lang.NoSuchMethodException: java.lang.String.mkString(java.lang.String)
at java.lang.Class.getMethod(Class.java:1624)
at .reflMethod$Method1(<console>:10)
at .<init>(<console>:10)
at .<clinit>(<console>:10)
at .<init>(<console>:7)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)

何故ですか?String が Java クラスだからでしょうか。この問題を回避できますか? これは Scala 実装のバグ/欠点ですか?

4

2 に答える 2

1

はい、これStringは Java クラスでありmkString、少し助けがなければメソッドはありません。

これは、JVM で実行し、String速度と Java コードとの互換性のためにそのネイティブ クラスを使用することの制限です。

は、 への暗黙的な変換を使用して、オンデマンドで にmkString追加されます。をString->StringOps にキャストすると、暗黙的な変換が適用されなくなるため、余分なメソッドがすべて失われます。StringStringOpsnameHasMkString

回避策は、交換することです

def f (name: HasMkString) = name.mkString ("-")

def f (name: HasMkString) =
  if (name.isInstanceOf[String]) name.asInstanceOf[String].mkString ("-")
  else name.mkString ("-")

または、構造型に明示的にキャストして型情報を破棄しないようにします。たとえば、

def f (name: HasMkString) = name.mkString ("-")
f ("John")  // Ok. Scala is smart enough to wrap the String here.
f ("John".asInstanceOf[HasMkString])  // Error. String type is hidden.

または、リフレクションを使用してコードが遅くなる可能性があるため、構造的な型付けは避けてください。

于 2013-09-01T00:40:21.890 に答える
1

@artemgr の回答に追加するとasInstanceOf、暗黙的な変換をトリガーしていないことに注意してください。

scala> type HasMkString = { def mkString(sep:String):String }
defined type alias HasMkString

scala> def f (name: HasMkString) = name.mkString ("-")
f: (name: HasMkString)String

scala> f("AAA")
res0: String = A-A-A
于 2013-09-01T06:57:29.500 に答える