Abstract private fields in Scala trait -


i happened find it's not allowed have abstract private fields in trait, is,

trait a1 {     //private val a: int         // not allowed     protected val b: int         // ok } 

and seems right such thing abstract class, if private fields constructor parameters, is,

abstract class a2 (private val i: int) // ok 

so guess trait doesn't have constructor parameters, there's no way initialize them, therefore no abstract private fields allowed.

if "protected", subclass can initialize them using pre-initialized fields. approach allows subclass see these fields.

what if want initialize them , hide them afterwards, in following example?

object holding {     trait trick {         protected val seed: int                     // can't private         final def magic: int = seed + 123     }      trait new_trick extends trick {         def new_magic: int = magic + 456         def the_seed: int = seed                    // [1]     }      def play: new_trick = new { val seed = 1 } new_trick       def show_seed(t: new_trick): int = t.the_seed   // [2] } 

i don't want able see seed, is, [2] (and [1]) shouldn't allowed. there way trait that?


as @randall , @pagoda_5b have pointed out, question doesn't make sense. luckily @régis , @axel22 have turned interesting question , provided pattern solving it.

a simple way keep val private while allowing sub-traits initalize define private initialize value returned protected method. sub-traits can define protected method change initial value, cannot access value itself. change this:

trait {   protected val foo: bar } 

into:

trait {   private val foo: bar = initfoo    protected def initfoo: bar } 

now, trait a can access val foo. sub-traits can set initial value of foo definint initfoo, cannot access foo itself:

trait b extends {   protected def initfoo: bar = ??? } 

obviously, initfoo still accessible sub-traits. not problem if initfoo creates new instance everytime (in other words, factory), might interested in making instance private a without being concerned having sub-traits being able create new instances of bar (irrespective of whether new instances equals foo per equals method).

but if concern (and in case seed fo type int , want hide value , not reference), can use additional trick allow sub-traits define initfoo prevent them (and sub-traits) being able call it. trick is, let's face it, pretty awful such simple need, illustrates nice pattern advanced access control. credits goes standard library authors idea (see http://www.scala-lang.org/api/current/index.html#scala.concurrent.canawait).

trait {   // "permit" call fooinit. instance can instantiate inita   abstract class inita private[this]()   // unique "permit"   private implicit def inita: inita = null    private def foo: int = fooinit   protected def fooinit( implicit init: inita ): int }  trait b extends {   protected def fooinit( implicit init: inita ): int = 123 } 

now, if b tries call initfoo, compiler complain not find implicit of type inita (the unique such instance a.inita , accesible in a) .

as said, it's bit awful , package private solution given axel22 easier alternative (although won't prevent defining sub-traits inside same package yours, defeating access restriction).


Comments

Popular posts from this blog

monitor web browser programmatically in Android? -

Shrink a YouTube video to responsive width -

wpf - PdfWriter.GetInstance throws System.NullReferenceException -