2016-06-29 7 views
5

Heute habe ich ein seltsames Problem mit Fall-Klasse-Konstruktoren aufgetreten. Ich wollte einen Konstruktor privat machen und es scheint, dass es kein Problem ist. Also habe ich es in einem meiner Projekte versucht und es funktioniert. Aber in einem anderen Projekt kann ich privaten Konstruktor aufrufen und es kompiliert. Ich dachte, es ist etwas mit meiner Idee, also habe ich eine eigenständige Klasse erstellt und mit scalac kompiliert. Und es kompiliert. Hier ist der Code:Scala-Fall-Klasse privaten Konstruktor ist nicht privat

package com.test 

object Main { 

    def main(args: Array[String]) { 
    val bar = Bar("12345") 
// bar.doStuff() 
    println(bar) 
    } 
} 

case class Bar private(foo: String){ 
    private def doStuff():Unit = println("stuff") 
} 

Das Komische ist, dass, wenn ich bar.doStuff Kommentar-() es nicht kompiliert werden. Ich gehe also davon aus, dass private Arbeiten in diesem Fall funktionieren, funktioniert aber irgendwie nicht für Konstrukteure. Was mache ich falsch? Scalac ist 2.11.8

Antwort

10

Die Bezeichnung ist eine Abkürzung für val bar = Bar("12345")val bar = Bar.apply("12345"), in anderen Worten, es ruft die Methode des apply (automatisch generiert) companion object der Fallklasse.

Das Companion-Objekt hat Zugriff auf den privaten Konstruktor, deshalb funktioniert es.

(Warum möchten Sie den Konstruktor einer Fallklasse private machen? Das klingt nicht wie eine gute Idee).

+4

Genau. 'val bar = neue Bar (" 12345 ")' wird nicht funktionieren – nmat

+0

Vielen Dank für Ihre Antwort. Ich wusste über die Methode anwenden, aber irgendwie habe ich nicht darüber nachgedacht. Was Ihre Frage angeht, möchte ich ein Feld haben, das in der Methode apply und nur dort initialisiert wird. –

+3

@ArtemMalinko es wird wahrscheinlich am einfachsten, es zu einer regulären Klasse (mit optional einem Companion-Objekt) zu machen, so dass Sie die volle Kontrolle über den Konstruktor und die 'Apply'-Methode haben. Beachten Sie, dass Fallklassen wirklich nur syntaktischer Zucker sind, Sie können auch alles tun, was Sie mit einem normalen Kurs brauchen (aber Sie müssen einige Dinge selbst schreiben). – Jesper

2

Wenn Sie Bar("abc") nicht kompilieren möchten, hier ist eine einfache Problemumgehung.

Schnell getestet in 2.12.3. Funktioniert nicht in 2.11.8

case class Bar private (value: String) 
object Bar { 
    private def apply(v: String) = new Bar(v) // makes the method private 
    def create(value: String): Bar = ... // your own implementation 
} 

val bar = Bar("abc") // compile error 
val bar = new Bar("abc") // compile error 
val bar = Bar.create("abc") // ok 
Verwandte Themen