Scala - попытка печати переопределенного метода toString

приведенный ниже код:

scala> class A {
 |     def hi = "Hello from A"
 |     override def toString = getClass.getName
 | }
defined class A

scala> val a = new A()
a: A = A

scala> a.toString
res10: String = A

scala> println(s"${a.toString}")
$line31.$read$$iw$$iw$A

При использовании выражения a.toString оно печатает ok, а не при использовании println(s"${a.toString}"). Задача getClass.getName. В других случаях он работает хорошо.

Заранее благодарим за помощь

Ответ 1

REPL фильтрует свой вывод, чтобы скрыть обложки шаблонов.

$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92).
Type in expressions for evaluation. Or try :help.

scala> class A
defined class A

scala> val a = new A
a: A = [email protected]

scala> a.getClass
res0: Class[_ <: A] = class A

scala> $intp.isettings.
allSettings   deprecation   deprecation_=   maxAutoprintCompletion   maxPrintString   toString   unwrapStrings

scala> $intp.isettings.unwrapStrings = false
$intp.isettings.unwrapStrings: Boolean = false

scala> a.getClass
res1: Class[_ <: A] = class $line3.$read$$iw$$iw$A

Вы также можете сравнить отсечение вывода:

scala> (1 to 1000).mkString
res2: String = 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629...
scala> println((1 to 1000).mkString)
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000

Прокрутите вправо, чтобы увидеть эллипсис в первой строке.

Ответ 2

Поскольку имена классов внутри REPL различны, REPL необходимо преобразовать внутренние имена назад. Он делает это достаточно хорошо при отображении строк, но не выполняется, когда строка передается внешнему методу, например. println или toList:

scala> a.toString
res1: String = A

scala> a.toString.toList
res2: List[Char] = List($, l, i, n, e, 4, ., $, r, e, a, d, $, $, i, w, $, $, i, w, $, A)

scala> "$line4.$read$$iw$$iw$A"
res3: String = A

Ответ 3

Запустите scala repl, используя: scala -Xprint: parser

Затем запустите последовательные команды. Вывод $line3. $Read $$ iw $$ iw $A представляет путь к объекту A. $line - это пакет, $read и $iw - объекты, в которых объект A вложен.

В случае println(s"${a.toString}")

scala> println(s"${a.toString}")
[[syntax trees at end of                    parser]] // <console>
package $line5 {
  object $read extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    object $iw extends scala.AnyRef {
      def <init>() = {
        super.<init>();
        ()
      };
      import $line3.$read.$iw.$iw.A;
      import $line4.$read.$iw.$iw.a;
      object $iw extends scala.AnyRef {
        def <init>() = {
          super.<init>();
          ()
        };
        val res0 = println(StringContext("", "").s(a.toString))
      }
    }
  }
}

[[syntax trees at end of                    parser]] // <console>
package $line5 {
  object $eval extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    lazy val $result = $line5.$read.$iw.$iw.res0;
    lazy val $print: String = {
      $line5.$read.$iw.$iw;  
      ""   <-- // SOMETHING OFF HERE! NO OUTPUT STRING BEING GENERATED?
    }
  }
}

$line3.$read$$iw$$iw$A

Теперь для случая a.toString:

scala> a.toString
[[syntax trees at end of                    parser]] // <console>
package $line6 {
  object $read extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    object $iw extends scala.AnyRef {
      def <init>() = {
        super.<init>();
        ()
      };
      import $line3.$read.$iw.$iw.A;
      import $line4.$read.$iw.$iw.a;
      object $iw extends scala.AnyRef {
        def <init>() = {
          super.<init>();
          ()
        };
        val res1 = a.toString
      }
    }
  }
}

[[syntax trees at end of                    parser]] // <console>
package $line6 {
  object $eval extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    lazy val $result = $line6.$read.$iw.$iw.res1;
    lazy val $print: String = {
      $line6.$read.$iw.$iw;  // *CORRECTLY GENERATES THE RESULT STRING.*
      "".$plus("res1: String = ").$plus(scala.runtime.ScalaRunTime.replStringOf($line6.$read.$iw.$iw.res1, 1000))
    }
  }
}

res1: String = A

Ответ 4

Это способ, которым REPL компилирует A. В простом приложении, как показано ниже, проблем нет... Каждая строка в REPL завернута в свой собственный пакет.. и это автоматически сгенерированное имя пакета - это то, что вы видите, добавленное к имени класса A.

object ScalaApp extends App {

      class A {
        def hi = "Hello from A"
        override def toString = getClass.getName
      }

      val a = new A()

      println(a.toString)

      println(s"${a.toString}")
    }