Suppose I have the following trait and object:
trait NoAnon {
val i: Int
}
object NoAnon {
def create = new NoAnon {
val i = 123
}
}
I would like to prevent anonymous instances of NoAnon from being created outside of the companion object. ie. only create in this example should be allowed to do this. I can enclose these within another object, and make the trait private to that object to accomplish this:
object Ctx {
private[Ctx] trait NoAnon {
val i: Int
}
object NoAnon {
def create = new Ctx.NoAnon {
val i = 123
}
}
}
Is it possible to do this without the enclosing object Ctx?
To be a little more clear, can traits mimic the functionality of a private abstract class constructor? That is, the following example, except with a trait.
abstract class NoAnon private[NoAnon] {
val i: Int
}
object NoAnon {
def create = new NoAnon {
val i = 123
}
}
Maybe you could use a class with a private constructor and extend that with your trait. You can even nest that class in the companion object:
trait NoAnon extends NoAnon.type#NoAnonCheck {
val i: Int
}
object NoAnon {
class NoAnonCheck private[NoAnon]
def create = new NoAnon {
val i = 1
}
}
Then if you tried:
new NoAnon { val i = 2 }
You get:
error: constructor NoAnonCheck in class NoAnonCheck cannot be accessed in <$anon: NoAnonCheck with NoAnon>
But you can use NoAnon.create. Other than adding something like this, I don't think there is currently a pure way to do this in Scala.
Of course as you know and as mentioned in the comments, the other options are to make the the trait private to the scope of an enclosing object or package.
Related
So I am a bit new to scala.
How does one write scala code to reference a method from case class's companion object in a generic fashion? I have tried a couple of different approaches and can't seem to find one that works.
Below is some sample code that works, but I have to manually build each subclass.
For example:
class One extends Act[LetterA] {
val intro = LetterA.sayhi
}
I would much rather do something like:
class AllOfThem[T <: LettersClass, S <: LettersSingleton] extends Act[T] {
val intro = S.sayhi
}
but I can't seem to find syntax that works or will compile. What is the proper way to do this, or am I looking for something that is not supported in the language? I recognise I am probably a little off on how I am structuring my classes and traits, but I am not sure how to best tackle this desired behaviour.
Additionally, is there a way to something similar to what I have commented out in the method 'actionTwo' in the Act class?
Sample Code listing:
trait LettersSingleton {
def sayhi() : String
}
trait LettersClass {
val id : Int
}
// trait Letters extends LettersClass with LettersSingleton { }
object LetterA extends LettersSingleton {
def sayhi = "Hi I am A"
}
object LetterB extends LettersSingleton {
def sayhi = "Hi I am B"
}
case class LetterA( val id : Int ) extends LettersClass { }
case class LetterB( val id : Int, val name:String ) extends LettersClass { }
abstract class Act[ T <: LettersClass ] {
val intro : String
def actionOne( a : T ) = {
println( a.id + " is my id" )
}
def actionTwo() = {
// println( T.sayhi )
}
}
class One extends Act[LetterA] {
val intro = LetterA.sayhi
}
class Two extends Act[LetterB] {
val intro = LetterB.sayhi
}
So you can't do exactly what you want, but you can get very close with the commonly used typeclass pattern:
//add a type parameter, now you have a typeclass
trait LettersSingleton[T] {
def sayhi() : String
}
//LettersClass stays the same
object Implicits {
//implicit classes/objects have to go inside an object
//create typeclass instances as implicit objects
implicit object LetterASingleton extends LettersSingleton[LetterA] {
def sayhi = "Hi I am A"
}
implicit object LetterBSingleton extends LettersSingleton[LetterB] {
def sayhi = "Hi I am B"
}
}
import Implicits._
//add an implicit parameter to the class
abstract class Act[ T <: LettersClass ](implicit singleton: LettersSingleton[T]) {
def actionTwo() = {
println( singleton.sayhi )
}
}
(new Act[LetterA]).actionTwo() //prints "Hi I am A"
(new Act[LetterB]).actionTwo() //prints "Hi I am B"
So basically what happens is any time you create a new Act[T], the compiler is going to try to fill in the implicit parameter for you by looking for any implicit objects or vals of the correct type in scope. So
val a = new Act[LetterA]
will actually become
val a = new Act[LetterA](LetterASingleton)
You'll notice that the singletons are no longer the companion objects of the case classes, which is fine. You have to define a trait regardless, so it doesn't make much different whether it's the companion object or some other object that implements it.
I am looking for a way to initialize a companion object with arguments. I tried this, it has the risk for re-instantiation.
private[mypackage] class A(in:Int) {
def method = {}
}
object A {
var singleton: Option[A] = None
def getInstance(): A = {
if(singleton.isDefined)
singleton.get
else {
throw InitializationException("Object not configured")
}
}
def getInstance(in:Int): A = {
singleton = Some(new A(in))
singleton.get
}
}
Is there a better way?
Pure Scala way
Scala allows you to create a singleton object of a type using object keyword. Scala ensures only one instance of A is available in the system.
private[myPackage] object A {
val configValue = Config.getInt("some_value")
def fn: Unit = ()
}
type of A object
scala> object A {}
defined object A
scala> :type A
A.type
more about singleton objects in scala Explanation of singleton objects in Scala
Guice Annotations
import com.google.inject.Singleton
#Singleton
class A (val value: Int) {
def fn: Unit = ()
}
Classic Java way
Use synchronized keyword to protect the getInstance from creating more than one object when called. of course constructor of the class has to be private
You can use a lazy val to delay creation of your singleton, and base it on a var that should be updated once during start-up sequence:
object A {
// will be instantiated once, on first call
lazy val singleton: A = create()
private var input: Option[Int] = None
// call this before first access to 'singleton':
def set(i: Int): Unit = { input = Some(i) }
private def create(): A = {
input.map(i => new A(i))
.getOrElse(throw new IllegalStateException("cannot access A before input is set"))
}
}
I have a library where an abstract class Base[T] is over a type T supplied by the user. There are many specific Base[T] sub-classes, some are over types T and S, like Specific[T, S], but this is irrelevant. The user might specify any T of course while creating and instance, but I want to treat it as T with a trait AdditionalAbilities or in other words I want to 'gift' the user's type with AdditionalAbilities. How can I do that in Scala? I hope the title is correct for this question.
Example (might not be syntactically correct)
class Specific[T **with trait Additional**]() extends Base[T](){
def doSomething() : T = {
val something = new T()
something.ability(2)
println(something.additional)
something
}
}
trait Additional{
var additional : Integer
def ability(i : Integer) : Unit = {
additional = i
}
}
Would work with any T.
When you define a parametric class you can require the parameter type to descend from a certain type:
trait AdditionalAbilities {
def doStuff(): Unit = println("Hey There")
}
object NoAbility extends AdditionalAbilities {
override def doStuff(): Unit = ()
}
abstract class Base[T] { ... }
class Specific[T <: AdditionalAbilities] extends Base[T] {
def f(t: T): Unit = t.doStuff()
}
Then when you try to instantiate a Specific type:
scala> new Specific[Int] {}
<console>:13: error: type arguments [Int] do not conform to class Specific's type parameter bounds [T <: AdditionalAbilities]
scala> val b = new Specific[NoAbility.type] {}
b: Specific[NoAbility.type] = $anon$1#517cd4b
scala> b.f(NoAbility)
//did nothing
Also, if you want to add a behaviour to an existing concrete class, you can do so at the time of instantiation:
trait CoolAbilities { def doStuff(): Unit = println("Hey there") }
class A { }
scala> val a = new A with CoolAbilities
a: A with CoolAbilities = $anon$1#6ad3381f
scala> a.doStuff()
Hey there
Perhaps implicit classes could help? Implicit classes allow you to add functionality to an existing type without needing to modify the existing type, or be the one instantiating it (so that you could mix in a trait).
The following compiles, and prints: 3
class Specific[T] {
implicit class TAdditional(t: T) {
var additional: Integer = 0
def ability(i: Integer) = {
additional = i
}
}
def doSomething(t: T) = {
doSomethingAdditional(t)
}
private def doSomethingAdditional(t: TAdditional) = {
t.ability(3)
println(t.additional)
}
}
val s = new Specific[Int]
s.doSomething(5)
Note: We need to do something to make sure we are accessing the same instance
of TAdditional, that's why I made the private doSomethingAdditional method that takes a TAdditional as an argument. If we call ability and additional in 'doSomething', separate instances of TAdditional would be created when we try to access #ability and #additional, and '0' would be printed.
I have the following trait:
trait Mappable {
def toMap = {
val mappableFields = this.getClass.getDeclaredFields.filter(...)
...
}
}
mappableFields lists this.declaredFields and then applies static filters to the list; as such it is invariant for each class that implements Mappable, and ideally I'd like to be able to put it in the subclasses' singleton objects or something along those lines. My current solution is
object Mappable {
import scala.collection.mutable.Map
private val fieldMap = Map[Class[_], Array[Field]]()
def getFieldMap(clazz: Class[_]) = {
fieldMap.get(clazz) match {
case Some(array) => array
case _ => {
val mapFields = clazz.getDeclaredFields.filter(...)
fieldMap.put(clazz, mapFields)
mapFields
}}}}
trait Mappable {
def toMap = {
val mappableFields = Mappable.getFieldMap(this.getClass)
...
}
}
but I'm wondering if there's a better solution e.g. one that doesn't require a call to Map#get. I can't turn the trait into a class.
You could do something like this:
trait Mappable {
def companion: MappableCompanion
def toMap = {
val mappableFields = companion.mappableFields
...
}
}
trait MappableCompanion {
def thisClass: Class[_]
val mappableFields = thisClass.getDeclaredFields.filter(...)
}
Subtypes of Mappable would then also define a companion object:
class Foo extends Mappable {
def companion = Foo
}
object Foo extends { val thisClass = classOf[Foo] } with MappableCompanion
If you don't like the early initializer you can make MappableCompanion a class.
I have a program structured as follows:
abstract class OuterClass
{
class InnerClass extends Actor
{
loop
{
react
{
case m: T => someFunction(m)
}
}
def someFunction(m: T)
{
...search function map for specific function...
specificFunction()
}
...extra methods here...
}
var functionmap=scala.sollection.mutable.Map.empty[String,()=>String]
var actorpool: ArrayBuffer[Actor]=new ArrayBuffer(0)
def main(args: Array[String])
{
...create X actors and add them to the pool...
populatefunctionmap
}
def populatefunctionmap() //defined elsewhere
}
class RunMe extends OuterClass
{
def populatefunctionmap()
{
...add some functions to the map...
}
}
The problem I have is that I would like to make use of the extra functions available within the actor instance that runs my functionmap functions. When I've tried using this it refers to the extending RunMe class. Using self just results in a not found: value self compiler error.
Is what I want to do possible? If so, how?
A couple of points I'd like to make about your code:
functionmap is both a var and mutable Map. Typically you only need it to be one or the other; not both.
Same goes for actorpool.
Access to shared, mutable state violates the design principles of the actor model.
Given the skeleton you provided, I'm assuming that you don't need to change the functionmap after it's been initialized. Instead of making it a mutable var, make it an immutable val.
You can do that by either an abstract val (shown here), or by a constructor parameter.
abstract class OuterClass {
class InnerClass extends Actor {
def act() {
loop {
react {
case m: T => someFunction(m)
}
}
}
def someFunction(m: T) {
// ...search functionmap for specific function...
for (specificFunction <- functionmap.get(key)) {
specificFunction()
}
}
}
// abstract val
val functionmap: Map[String, () => String]
val actorpool: ArrayBuffer[Actor]=new ArrayBuffer(0)
def main(args: Array[String]) {
// ...create X actors and add them to the pool...
}
}
class RunMe extends OuterClass {
val functionmap = {
// ...build the function map...
}
}
If you need to change functionmap after the actors are created, then InnerClass needs to have a var which holds their own functionmap, which you change by sending messages to the actors.
If I understand correctly, your question has nothing to do with Actors. It boils down to:
abstract class Outer {
class Inner {
def innerf = 42
}
}
class RunMe extends Outer {
val inst = new Inner
def ref = inst.innerf
}
scala> (new RunMe).ref
res0: Int = 42
scala> val r = new RunMe
scala> (new r.Inner).innerf
res1: Int = 42
The inner class's methods are only available on an instance of that inner class, so you need to start by making some instances.
If you'd like to access methods of InnerClass from the functions in functionmap, then it should be of type InnerClass => String, so you have the instance you want to call methods on.