I wonder if it is possible to inherit auxiliary constructors in Scala?
I tested this code, and it complained
temp.scala:18: error: too many arguments for constructor Child: ()this.Child
val a = new Child(42)
^
abstract class Father {
var value: Int = 0
protected def setValue(v: Int) = {
value = v
}
protected def this(v: Int) = {
this()
setValue(v)
}
}
class Child extends Father {
}
val a = new Child(42)
But if i put
protected def this(v: Int) = {
this()
setValue(v)
}
in the Child class, everything is all right.
Absolutely not, and your example demonstrates why. You've introduced a mutable variable value that may or may not be initialised - depending on the exact constructor used.
This is a potential source for a great many problems, and so Scala made the decision that all object creation should ultimately be directed via the primary constructor, this ensuring consistent initialisation.
If you want value to have a default value, then you can specify it as a default parameter (in 2.8+):
abstract class Father(val value : Int = 0)
or you can use the auxiluary constructor to achieve the same effect in Scala 2.7:
abstract class Father(val value : Int) {
def this() = this(0)
}
With Father defined in either of the above ways, the following definitions of child are both valid:
class Child(v:Int) extends Father(v)
class Child extends Father()
You can also make value a var if you absolutely have to, but I strongly advise against it.
If the semantics of value mean that it's valid to not be initialised, then the correct Scala idiom is to declare it as Option[Int]:
abstract class Father(val value : Option[Int] = Some(0))
Your Child constructor have no parameter and you are trying to instanciate it with one ! You have to declare a parameter in your Child constructor and then pass it to the Father class, for example:
class Child(v:Int) extends Father(v) {
}
val a = new Child(42)
Related
Scala throws "reassignment to val" error for the following code.
abstract case class Gun(var bulletCount:Int)
class Pistol(bulletCount:Int) extends Gun(bulletCount){
def fire() { bulletCount=bulletCount-1 }
}
Anything I missed here?
For starters, you should consider case class as final, and not extend them.
Second, do not use var with case class, you should rather create a copy of a case class to get one of its field changed.
Third, if you want a common type, you can use a base trait.
All in one, here's what it could look like:
sealed trait Gun {
def bulletCount: Int
}
case class Pistol(bulletCount: Int) extends Gun {
def fire(): Pistol = copy(bulletCount=bulletCount)
}
You're referring to bulletCount field generated by Pistol primary constructor parameter. To set base class variable, you need to directly call field using super:
class Pistol(bulletCount: Int) extends Gun(bulletCount) {
def fire(): Unit = {
super.bulletCount = super.bulletCount - 1
}
}
Alternatively, you can label parameter-generated field with override var:
class Pistol(override var bulletCount: Int) extends Gun(bulletCount) {
def fire(): Unit = {
bulletCount = bulletCount - 1
}
}
On a side note, as Frederic A. suggested in his answer, you should avoid inheriting case classes. They are syntactic sugar, and code generation don't work over inheritance - you'll need to implement all the fancy stuff like apply or unapply methods in companion class all by yourself. Scala compiler team tried to support case class to case class inheritance, but discovered that it breaks structural equality and lots of other things.
In the following example, is there a way to avoid that implicit resolution picks the defaultInstance and uses the intInstance instead? More background after the code:
// the following part is an external fixed API
trait TypeCls[A] {
def foo: String
}
object TypeCls {
def foo[A](implicit x: TypeCls[A]) = x.foo
implicit def defaultInstance[A]: TypeCls[A] = new TypeCls[A] {
def foo = "default"
}
implicit val intInstance: TypeCls[Int] = new TypeCls[Int] {
def foo = "integer"
}
}
trait FooM {
type A
def foo: String = implicitly[TypeCls[A]].foo
}
// end of external fixed API
class FooP[A:TypeCls] { // with type params, we can use context bound
def foo: String = implicitly[TypeCls[A]].foo
}
class MyFooP extends FooP[Int]
class MyFooM extends FooM { type A = Int }
object Main extends App {
println(s"With type parameter: ${(new MyFooP).foo}")
println(s"With type member: ${(new MyFooM).foo}")
}
Actual output:
With type parameter: integer
With type member: default
Desired output:
With type parameter: integer
With type member: integer
I am working with a third-party library that uses the above scheme to provide "default" instances for the type class TypeCls. I think the above code is a minimal example that demonstrates my problem.
Users are supposed to mix in the FooM trait and instantiate the abstract type member A. The problem is that due to the defaultInstance the call of (new MyFooM).foo does not resolve the specialized intInstance and instead commits to defaultInstance which is not what I want.
I added an alternative version using type parameters, called FooP (P = Parameter, M = Member) which avoids to resolve the defaultInstance by using a context bound on the type parameter.
Is there an equivalent way to do this with type members?
EDIT: I have an error in my simplification, actually the foo is not a def but a val, so it is not possible to add an implicit parameter. So no of the current answers are applicable.
trait FooM {
type A
val foo: String = implicitly[TypeCls[A]].foo
}
// end of external fixed API
class FooP[A:TypeCls] { // with type params, we can use context bound
val foo: String = implicitly[TypeCls[A]].foo
}
The simplest solution in this specific case is have foo itself require an implicit instance of TypeCls[A].
The only downside is that it will be passed on every call to foo as opposed to just when instantiating
FooM. So you'll have to make sure they are in scope on every call to foo. Though as long as the TypeCls instances are in the companion object, you won't have anything special to do.
trait FooM {
type A
def foo(implicit e: TypeCls[A]): String = e.foo
}
UPDATE: In my above answer I managed to miss the fact that FooM cannot be modified. In addition the latest edit to the question mentions that FooM.foo is actually a val and not a def.
Well the bad news is that the API you're using is simply broken. There is no way FooM.foo wille ever return anything useful (it will always resolve TypeCls[A] to TypeCls.defaultInstance regardless of the actual value of A). The only way out is to override foo in a derived class where the actual value of A is known, in order to be able to use the proper instance of TypeCls. Fortunately, this idea can be combined with your original workaround of using a class with a context bound (FooP in your case):
class FooMEx[T:TypeCls] extends FooM {
type A = T
override val foo: String = implicitly[TypeCls[A]].foo
}
Now instead of having your classes extend FooM directly, have them extend FooMEx:
class MyFoo extends FooMEx[Int]
The only difference between FooMEx and your original FooP class is that FooMEx does extend FooM, so MyFoo is a proper instance of FooM and can thus be used with the fixed API.
Can you copy the code from the third party library. Overriding the method does the trick.
class MyFooM extends FooM { type A = Int
override def foo: String = implicitly[TypeCls[A]].foo}
It is a hack, but I doubt there is anything better.
I do not know why this works the way it does. It must be some order in which the type alias are substituted in the implicitly expression.
Only an expert in the language specification can tell you the exact reason.
I've a got a trait:
trait A {
def some: Int
}
and an object mixing it in:
object B extends A {
def some = 1
}
The question is, is there a way to declare some in A in a way that all inheriting objects have to declare the some method as protected for example? Something that would make the compiler yell at the above implementation of some in B?
UPDATE:
Just a clarification on the purpose of my question: Within an organization, there are some software development standards that are agreed upon. These standards, for example 'The some method is to always be declared as private when inheriting from trait A', are in general communicated via specs or documents listing all the standards or via tools such as Jenkins, etc... I am wondering if we could go even further and have these standards right in the code, which would save a lot of time correcting issues raised by Jenkins for example.
UPDATE 2:
A solution I could think of is as follows:
abstract class A(
protected val some: Int
){
protected def none: String
}
Use an abstract class instead of a trait and have the functions or values that I need to be protected by default passed in the constructor:
object B extends A(some = 1) {
def none: String = "none"
}
Note that in this case, some is by default protected unless the developer decides to expose it through another method. However, there will be no guarantee that, by default, none will be protected as well.
This works for the use case I described above. The problem with this implementation is that if we have a hierarchy of abstract classes, we would have to add the all the constructor parameters of the parent to every inheriting child in the hierarchy. For example:
abstract class A(
protected val some: Int
)
abstract class B(
someImp: Int,
protected val none: String
) extends A(some = someImp)
object C extends B(
someImp = 1,
none = "none"
)
In contrast, using traits, we could have been able to simply write:
trait A{
protected val some: Int
}
trait B extends A{
protected val none: String
}
object C extends B{
val some = 1
val none = "none"
}
I don't see any straight way to restrict subclasses from choosing a wider visibility for inherited members.
It depends on why you want to hide the field some, but if the purpose is just to forbid end-users from accessing the field, you can use a slightly modified form of the cake pattern:
trait A {
trait A0 {
protected def some: Int
}
def instance: A0
}
object B extends A {
def instance = new A0 {
def some = 5
}
}
Yeah, it looks nasty but the compiler will yell when someone tries to do:
B.instance.some
Another version of this solution is just to do things like in your example (adding protected to the member "some" in A), but to never expose directly a reference of type B (always return references of type A instead)
Why does Scala behave like this ?
More importantly, how can this code be fixed ?
I am asking this question because I have complicated types that I need to use in constructor declarations in several subclasses and I want to stay DRY.
class Parent{
type IntAlias=Int
}
class Child (val i1:IntAlias=3) extends Parent{ //Compilation error, why ?
val i2:IntAlias= 1 //No problem here!
}
Compiler error:
not found: type IntAlias
class Child (val i1:IntAlias=3) extends Parent{
^
In your definition, IntAlias is a member of class Parent. So without an instance of Parent you cannot access that member. You can read your second case as val i2: this.IntAlias = 1. Here you have access to the instance this.
This is similar to the following for values instead of types:
class Parent {
def intValue: Int = 1234
}
class Child(val x: Int = intValue) extends Parent // does not compile
So you must put that member in a different scope, for example a companion object:
object Parent {
type IntAlias = Int
}
import Parent.IntAlias
class Child(val i1: IntAlias = 3) extends Parent {
val i2: IntAlias = 1
}
I have an parent class, and several child classes. What I want is when specific setter methods are called on instances of the child classes, a boolean value for "is synchronized" in the parent class is set to false. It should be possible to create child classes in either a synchronized or an unsynchronized state.
This is what I came up with:
class A(protected var isSync: Boolean) {
}
class B(var value:String, isSync: Boolean) extends A(isSync) {
override def value_=(value:String): Unit = {
this.isSync = false
this.value = value
}
}
Now, this doesn't compile for a number of reasons: the assignment of value to this.value is ambiguous; the var annotation already defines value_=; and this.isSync references the local constructor field isSync, instead of the (writable) parent field.
This question on Stack Overflow pointed out that I should use __value (or any name that isn't value) as a private var in the constructor, and define the setter myself. After some more tinkering, I came up with the following code that compiles and works:
class A(protected var isSync: Boolean) {
}
class B(private var __value: String, private val __isSync: Boolean)
extends A(__isSync) {
def value = __value
def value_=(value: String) = {
this.isSync = false
this.__value = value
}
}
However, this code feels so rancid that by now I suspect I'm making a (if not more) fundamental mistake. Could anyone please correct me?
Thus the concrete questions are:
Are there (and if, which) fundamental flaws in what I'm trying to implement? For some context: the objects, when changed, can (and probably have to) be synchronized with a server.
What is the right/best way to pass parameters to a class you extend?
What is the right/best way to override the setter generated by var (or generally provide your own setter implementation)?
About question 1: I guess that you want to track whether the object has been changed since last time it was copied to the server, don't you? That's sensible, as long as the copy on the server cannot be modified: otherwise ensuring consistency of the replica is more complex (replica consistency is the keyword for googling, but I wouldn't recommend it).
For clarity, I would talking about being clean or dirty - synchronized reminds me too closely of the synchronized Java statement.
About question 2, you don't need to make __isSync a private val (which will be stored in the class), you can leave it as a constructor parameter. As long as it is not used (other than in the invocation of A's constructor) __isSync should not take additional space in instances of B. I removed the private val annotation there, obtaining this code which compiles correctly as expected.
class A(protected var isSync: Boolean) {
}
class B(private var __value: String, __isSync: Boolean)
extends A(__isSync) {
def value = __value
def value_=(value: String) = {
this.isSync = false
this.__value = value
}
}
About aesthetics and question 3: I would simply avoid the double underscore. Similar examples from Programming in Scala (Sec 18.2) simply use shorter names. They also use private[this] to prevent access to the member from other instances of the same class. Finally, you can remove {} after the class decl. in this example (even if maybe not in your code).
Thus we'd get code like this, which is close to the examples I already mentioned:
class A(protected var isSync: Boolean)
class B(private[this] var v: String, sync: Boolean)
extends A(sync) {
def value = v
def value_=(value: String) = {
isSync = false
v = value
}
}