I have something like the following code (I simplified it):
trait A {
val CONST_VALUE = 10
}
class B(someValue: Int, values: Array[Int]) extends A {
//some methods
}
object B {
def apply(someValue: Int) = B(someValue, Array.ofDim[Array[Byte]](someValue).map(block => Array.fill[Byte](A.CONST_VALUE)(0)))
}
Basically, I declared a constant CONST_VALUE in the trait A. I am trying to use it in the companion object B to instantiate the class B. However, I can't access A.CONST_VALUE from the companion object B.(I'm getting a compilation error).
So how could I do this?
You can't do this.
First of all, object B is the companion object to class B, not to trait A. Companions need to have the same name and be defined in the same compilation unit.
Secondly, CONST_VALUE is an instance field of trait A. It is a member of an instance of A, not a member of A.
Thirdly, when you say A.CONST_VALUE you are basically calling the method CONST_VALUE on A. But you can only call methods on objects/values. A is not an object, it is a type, types and values live in different worlds, you cannot mix the two.
And fourth, your CONSTANT_VALUE is misleadingly named: only final vals are constant value definitions, so your CONSTANT_VALUE is not actually a constant value.
Fifth, your apply method calls itself (B() is syntactic sugar for B.apply()), and thus needs a return type annotation.
Sixth, your apply method calls itself with two arguments, but it is defined with only one parameter.
Seventh, you create an Array[Array[Byte]], but it is not clear to me why you want to do that and what you need it for.
That's a whole truckload of problems (especially considering that there are only a handful of lines of code to begin with), which you need to fix one-by-one. Here's one possible partial solution, but it is not clear to me what it is exactly that you are trying to achieve.
trait A
object A {
final val CONST_VALUE = 10
}
class B(someValue: Int, values: Array[Int]) extends A {
//some methods
}
object B {
def apply(someValue: Int): B = new B(
someValue,
Array.ofDim[Array[Byte]](someValue).map(block => Array.fill[Byte](A.CONST_VALUE)(0)))
}
Declare val CONST_VALUE = 10 inside the companion object A instead of trait A. Also corrected the apply method definition in object B
trait A {
}
object A {
final val CONST_VALUE = 10
}
class B(someValue: Int, values: Array[Int]) extends A {
//some methods
}
object B {
def apply(someValue: Int) = new B(someValue, Array.ofDim[Int](someValue).flatMap(block => Array.fill[Int](A.CONST_VALUE)(0)))
}
Related
I have following two classes.
class A (name: String) {
}
object A {
}
According to definition of Singleton, we can have only one object of that type. However I am able to create two different objects of type A using following piece of code.
object B {
def main(args: Array[String]): Unit = {
val a = new A("Vinod")
println(a)
val b = new A("XYZ")
println(b)
}
}
can someone please explain me, where my understanding is not correct?
An object by itself is a singleton. It has its own class and no other instance of the same class exist at runtime.
However, the pattern you describe here is different: object A is not an instance of class A unless you make it so using object A extends A. You could make it the only instance of class A by making class A a sealed class, but this is unnecessary in almost all cases.
If you really want the singleton pattern, drop the class and use only object A, all of its members will be "static" in the sense of Java.
Note that the actual type of object A can be referred to as A.type, which by default is completely unrelated to type A if class A exists. Again, A.type could be a subtype of A if you explicitly make it so.
The companion object is not an instance of the companion class. They're not even the same type.
class A
object A {
var state = 0
def update() :Unit = state = state + 1
}
val abc :A = new A //instance of class A
val xyz :A.type = A //2nd reference to object A
// both reference the same singleton object
xyz.update() //res0: Unit = ()
A.state //res1: Int = 1
abc.state //Error: value state is not a member of A$A2521.this.A
the companion object can be thought of as the static space of a class. if you want to make A a singleton you can make it an object rather than a class
new A refers to class A (which is not a singleton), not to object A. You can easily check it: if you remove class A, the new A lines will no longer compile.
Also note that objects aren't necessarily singletons: they can be nested inside classes or traits, in this case there is one for each instance of the outer type.
I want to have a collection of objects, each object a companion of a different class, which classes all share a common method defined in a superclass that can be invoked when looping through the collection with a foreach(). I want the constructors of these sibling-classes to have the same named parameters and default parameter values as each other. Finally, I want to minimize repeated code.
Thus far, I am trying to do this with case classes, since--if it worked--it would eliminate all the duplicated code of the companion-objects for each type. The problem is that if I put all these companion objects into a Set, when I take them out again I lose the default parameters and parameter names.
Here is some example code of what I am describing:
trait MyType {
val param: String
def label = param // all instances of all subclasses have this method
}
case class caseOne(override val param: String = "default") extends MyType
case class caseTwo(override val param: String = "default") extends MyType
object Main extends App {
// I can construct instances using the companion objects' `apply()` method:
val works1 = caseOne(param = "I have been explicitly set").label
// I can construct instances that have the default parameter value
val works2 = caseOne().label
// But what I want to do is something like this:
val set = Set(caseOne, caseTwo)
for {
companion <- set
} {
val fail1 = companion() // Fails to compile--not enough arguments
val fail2 = companion(param = "not default") // Fails also as param has lost its name
val succeeds = companion("nameless param") // this works but not what I want
println(fail1.label + fail2.label) // this line is my goal
}
}
Notably if the Set has only one element, then it compiles, suggesting the inferred type of the multi-element Set lacks the parameter name--even though they are the same--and the default values. Also suggesting that if I gave the Set the right type parameter this could work. But what would that type be? Not MyType since that is the type of the companion classes rather that the objects in the Set.
I could define the companion objects explicitly, but that is the repeated code I want to avoid.
How can I loop through my collection, constructing instances of MyType subclasses on each iteration, with constructors that have my desired parameter names and default values? All while minimizing repeated code?
Update: Originally the example code showed caseOne and caseTwo as having different default values for param. That was incorrect; they are now the same.
You're not going to be able to get exactly what you want since you don't really have much control over the auto-generated companion objects. In particular for this to work they would all need to extend a common trait. This is why it fails to compile when the set has more than one companion object; even though they all have a method with the same signature, they don't extend a common trait for the compiler to utilize.
You can use a nested case class and get something very similar though:
trait MyType {
val param: String
def label = param // all instances of all subclasses have this method
}
abstract class MyTypeHelper(default: String) {
case class Case(param: String) extends MyType
def apply(param: String) : Case = Case(param)
def apply(): Case = apply(default)
}
object One extends MyTypeHelper("default one")
object Two extends MyTypeHelper("default two")
object Example {
val works1 = One(param = "I have been explicitly set").label
val works2 = One().label
val set = Set(One, Two)
for {
companion <- set
} {
val a = companion()
val b = companion(param = "not default")
val c = companion("nameless param")
println(a.label + b.label)
}
}
Instead of having a caseOne type, you have One.Case, but it still implements MyType so you shouldn't have any issue anywhere else in the code that uses that trait.
I have something like below that I want to compile
trait T{
def a: Int
}
class A private(val a: Int, a2: Int) extends T{
def add(b: Int): A = new A(a + b, a2 + 2*b)
}
object T{
def make(a: Int): A = {
new A(a, 2*a) // doesn't compile
}
Here class A has a private constructor because I want the only way to construct a A is to pass through the constructor T.make or with the updated method A.add (which in this example both garantie that a2 = 2*a).
But because A constructor is private, it cannot be access by the parent trait T. Same goes for protected. Basically, I would need an inversed protected?
Note: A solution that is not satisfying is to lower (too much) the restriction on A constructor, maybe to package-private. But I don't want any other construction possible but the ones that were planned. I could lower the constraint to all code in the current file, but I don't know how to do that either.
A few options.
You can rename your object T to object A - then it will have access to A's private members
You can make class A inner to object T - then you can make the constructor private[T], and T will have access to it.
You can also make it package-private. You are mistaken when you say that it would be "lowering restriction too much". A package in scala doesn't have to be an entire directory. It doesn't even need to be the whole file. You have complete control over its content, and the purpose of that is to be able to do exactly what you are trying to do here.
Maybe you should put make(..) into companion object of class A rather than companion object of trait T.
object A {
def make(a: Int): A = {
new A(a, 2 * a)
}
}
I have the following where I set information and extractors for different schemes of data:
trait DataScheme {
type Type <: List[Any]
class ExtractorMethods(ticker: String, dataList: List[Type]) {
def getDatetime(datum: Type): Date = new Date(datum(columnIndex(Names.datetime)).toString)
def upperDatum(date: Date): Type = dataList.minBy(datum => getDatetime(datum) >= date)
def lowerDatum(date: Date): Type = dataList.maxBy(datum => getDatetime(datum) <= date)
}
}
trait IndexScheme extends DataScheme {
type Type = (Date, Double, Double, Double, Double, Long)
class ExtractorMethods(ticker: String, dataList: List[Type]) extends super.ExtractorMethods(ticker: String, dataList: List[Type]){
def testing12(int: Int):Int = 12
val test123 = 123
}
}
I want anything extending DataScheme to use its ExtractorMethods methods (e.g. lowerDatum) but also have its own methods (e.g. testing12).
There is a class definition for lists of data elements:
class Data[+T <: DataScheme](val ticker: String, val dataList: List[T#Type], val isSorted: Boolean)
(implicit m: Manifest[T], mm: Manifest[T#Type]) extends Symbols {
def this(ticker: String, dataList: List[T#Type])(implicit m: Manifest[T], mm: Manifest[T#Type]) = this(ticker, dataList, false)(m: Manifest[T], mm: Manifest[T#Type])
val dataScheme: T
val extractorMethods = new dataScheme.ExtractorMethods(ticker, dataList.asInstanceOf[List[dataScheme.Type]])
}
A Data class should make accessible the methods in ExtractorMethods of the scheme so they can be used in the main program through the instance of Data that has been defined. For example if sortedData is an instance of Data[IndexScheme], the following works:
val lowerDatum = sortedData.extractorMethods.lowerDatum(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2010-03-31 00:00:00"))
but this does not:
val testing = sortedData.extractorMethods.testing12(123)
because 'testing 123 is not a member of sortedData.dataScheme.extractorMethods'. So my question is how can the subclasses of ExtractorMethods in the subtraits of DataScheme like IndexScheme be made accessible? How is it possible using Manifests and TypeTags? Thanks.
So you want the generic class Data[DataScheme] or Data[IndexScheme] to have access to the methods of whichever type Data has been parameterised with. You've tried to do this several different ways, from the evidence in your code.
To answer your last question - manifests can't help in this particular case and TypeTags are only part of the answer. If you really want to do this, you do it with mirrors.
However, you will have to make some changes to your code. Scala only has instance methods; there are no such things as static methods in Scala. This means that you can only use reflection to invoke a method on an instance of a class, trait or object. Your traits are abstract and can't be instantiated.
I can't really tell you how to clean up your code, because what you have pasted up here is a bit of a mess and is full of different things you have tried. What I can show you is how to do it with a simpler set of classes:
import scala.reflect.runtime.universe._
class t1 {
class Methods {
def a = "a"
def b = "b"
}
def methods = new Methods
}
class t2 extends t1 {
class Methods extends super.Methods {
def one = 1
def two = 2
}
override def methods = new Methods
}
class c[+T <: t1](implicit tag: TypeTag[T]) {
def generateT = {
val mirror = runtimeMirror(getClass.getClassLoader)
val cMirror = mirror.reflectClass(typeOf[T].typeSymbol.asClass)
cMirror.reflectConstructor(typeOf[T].declaration(nme.CONSTRUCTOR).asMethod)
}
val t = generateT().asInstanceOf[T]
}
val v1 = new c[t1]
val v2 = new c[t2]
If you run that, you'll find that v1.t.methods gives you a class with only methods a and b, but v2.t.methods gives a class with methods one and two as well.
This really is not how to do this - reaching for reflection for this kind of job shows a very broken model. But I guess that's your business.
I stick by what I said below, though. You should be using implicit conversions (and possibly implicit parameters) with companion objects. Use Scala's type system the way it's designed - you are fighting it all the way.
ORIGINAL ANSWER
Well, I'm going to start by saying that I would never do things the way you are doing this; it seems horribly over-complicated. But you can do what you want to do, roughly the way you are doing it, by
Using mixins
Moving the extractorMethods creation code into the traits.
Here's a greatly simplified example:
trait t1 {
class Methods {
def a = "a"
def b = "b"
}
def methods = new Methods
}
trait t2 extends t1 {
class Methods extends super.Methods {
def one = 1
def two = 2
}
override def methods = new Methods
}
class c1 extends t1
val v1 = new c1
// v1.methods.a will return "a", but v1.methods.one does not exist
class c2 extends c1 with t2
val v2 = new c2
// v2.methods.a returns "a" and v2.methods.one returns 1
I could replicate your modus operandi more closely by defining c1 like this:
class c1 extends t1 {
val myMethods = methods
}
in which case v1.myMethods would only have methods a and b but v2.myMethods would have a, b, one and two.
You should be able to see how you can adapt this to your own class and trait structure. I know my example doesn't have any of your complex type logic in it, but you know better than I what you are trying to achieve there. I'm just trying to demonstrate a simple mechanism.
But dude, way to make your life difficult...
EDIT
There are so many things I could say about what is wrong with your approach here, both on the small and large scale. I'm going to restrict myself to saying two things:
You can't do what you are trying to do in the Data class because it is abstract. You cannot force Scala to magically replace an uninitialised, abstract method of a non-specific type with the specific type, just by littering everything with Type annotations. You can only solve this with a concrete class which provides the specific type.
You should be doing this with implicit conversions. Implicits would help you do it the wrong way you seem fixated on, but would also help you do it the right way. Oh, and use a companion object, either for the implicits or to hold a factory (or bot).
I'm trying to figure out how to .clone my own objects, in Scala.
This is for a simulation so mutable state is a must, and from that arises the whole need for cloning. I'll clone a whole state structure before moving the simulation time ahead.
This is my current try:
abstract trait Cloneable[A] {
// Seems we cannot declare the prototype of a copy constructor
//protected def this(o: A) // to be defined by the class itself
def myClone= new A(this)
}
class S(var x: String) extends Cloneable[S] {
def this(o:S)= this(o.x) // for 'Cloneable'
def toString= x
}
object TestX {
val s1= new S("say, aaa")
println( s1.myClone )
}
a. Why does the above not compile. Gives:
error: class type required but A found
def myClone= new A(this)
^
b. Is there a way to declare the copy constructor (def this(o:A)) in the trait, so that classes using the trait would be shown to need to provide one.
c. Is there any benefit from saying abstract trait?
Finally, is there a way better, standard solution for all this?
I've looked into Java cloning. Does not seem to be for this. Also Scala copy is not - it's only for case classes and they shouldn't have mutable state.
Thanks for help and any opinions.
Traits can't define constructors (and I don't think abstract has any effect on a trait).
Is there any reason it needs to use a copy constructor rather than just implementing a clone method? It might be possible to get out of having to declare the [A] type on the class, but I've at least declared a self type so the compiler will make sure that the type matches the class.
trait DeepCloneable[A] { self: A =>
def deepClone: A
}
class Egg(size: Int) extends DeepCloneable[Egg] {
def deepClone = new Egg(size)
}
object Main extends App {
val e = new Egg(3)
println(e)
println(e.deepClone)
}
http://ideone.com/CS9HTW
It would suggest a typeclass based approach. With this it is possible to also let existing classes be cloneable:
class Foo(var x: Int)
trait Copyable[A] {
def copy(a: A): A
}
implicit object FooCloneable extends Copyable[Foo] {
def copy(foo: Foo) = new Foo(foo.x)
}
implicit def any2Copyable[A: Copyable](a: A) = new {
def copy = implicitly[Copyable[A]].copy(a)
}
scala> val x = new Foo(2)
x: Foo = Foo#8d86328
scala> val y = x.copy
y: Foo = Foo#245e7588
scala> x eq y
res2: Boolean = false
a. When you define a type parameter like the A it gets erased after the compilation phase.
This means that the compiler uses type parameters to check that you use the correct types, but the resulting bytecode retains no information of A.
This also implies that you cannot use A as a real class in code but only as a "type reference", because at runtime this information is lost.
b & c. traits cannot define constructor parameters or auxiliary constructors by definition, they're also abstract by definition.
What you can do is define a trait body that gets called upon instantiation of the concrete implementation
One alternative solution is to define a Cloneable typeclass. For more on this you can find lots of blogs on the subject, but I have no suggestion for a specific one.
scalaz has a huge part built using this pattern, maybe you can find inspiration there: you can look at Order, Equal or Show to get the gist of it.