2017-10-03 3 views
0

Ich habe bereits über Probleme mit Objekten gelesen, die von Companion-Klassen erben.Scala-Klasse Singleton mit nicht-Standard-Konstruktor Parameter

Zum Beispiel:

Aber ich habe ein bisschen anders Problem (ich bin nicht sicher, dass es ein Fehler ist)

ich folgendes haben Code:

class Scala(name: String) 

import Scala._ 

object Scala extends Scala(TEST_NAME){ 
    val TEST_NAME = "test name" 
} 

Beachten Sie, dass ich Variable im Bereich des Companion-Objekts definiert und dann an den Konstruktor von Super übergeben.

Ich erhalte die folgenden Kompilierungsfehler:

Scala.scala:5: error: super constructor cannot be passed a self reference 
unless parameter is declared by-name 

object Scala extends Scala(TEST_NAME){ 
         ^
one error found 

Weitere Varianten, die ich versucht habe:

Call by name:

class Scala(name: => String) 

import Scala._ 

object Scala extends Scala(TEST_NAME){ 
    val TEST_NAME = "test name" 
} 

Named Argument:

class Scala(name: String) 

import Scala._ 

object Scala extends Scala(name = TEST_NAME){ 
    val TEST_NAME = "test name" 
} 

Beide o f sie:

class Scala(name: => String) 

import Scala._ 

object Scala extends Scala(name = TEST_NAME){ 
    val TEST_NAME = "test name" 
} 

Einige Umwelt-Details:

  • java: java version "1.8.0_144"
  • javac: javac 1.8.0_144
  • scala: Scala code runner version 2.12.3
  • scalac: Scala compiler version 2.12.3
  • OS: Darwin ***.local 17.0.0 Darwin Kernel Version 17.0.0: Thu Aug 24 21:48:19 PDT 2017; root:xnu-4570.1.46~2/RELEASE_X86_64 x86_64

Update:

Für alle, die in der Auflösung dieser interessiert ist:

+0

Ich glaube nicht, dass die Gesellschaft hier irgendeine Rolle spielt –

+0

@EduardoParejaTobes Sie meinen, dass es keine Notwendigkeit in der Gesellschaft gibt, ja? –

+0

yup, das ist ähnlich wie https://stackoverflow.com/q/32203867/614394 aber für Werte. Ich denke, es ist in Ordnung für Typen und falsch für Werte :) –

Antwort

0

Wenn Ihr Code oben kompilieren würde, dann könnten Sie schreiben

class A(val x: String) 

object B extends A(B.x_again) { 

    val x_again = x 
} 

was sicherlich nicht gut aussieht.

+0

Ja, ich stimme zu, dass es ein bisschen seltsam aussieht. –

1

Sie können eine obskure Funktion verwenden, die in Scala 3: frühe Initialisierer entfernt wird. Damit können Sie den Init-Code angeben, der vor dem Aufruf des Superklassenkonstruktors ausgeführt werden soll.

class Scala(name: String) 

object Scala extends { 
    val TEST_NAME: String = "test name" 
} with Scala(TEST_NAME) { /* rest of object code */ } 

Beachten Sie, dass Import ist nicht erforderlich - TEST_NAME ist bereits im Rahmen.


Hier ist ein Scastie snippet zu beweisen, dass es funktioniert.

+0

Vielen Dank für Ihre Antwort. Also, was ist die Lösung meiner Frage? Ist es ein Fehler? Randkasten? –

+0

@AndriiAbramov Ich weiß es nicht. Ich würde einen Fehler nennen, dass der Name-Name-Parameter nicht funktioniert, während die Nachricht vorschlägt, dass es sollte (besonders wenn ältere Versionen von Scala das unterstützen, was ich jetzt nicht überprüfen kann), aber es ist wahrscheinlich auch genug von einem Randfall, da schien sich zumindest seit dem 2.10 niemand mehr darum zu kümmern. –

2

Für Ihren eingeschränkten Anwendungsfall:

scala> class C(s: String) ; object X extends C(X.x) { final val x = "hello, world" } 
defined class C 
defined object X 

Die konstante Wert Definition inlined (gemäß der Spezifikation).