I'm writing a script to automatically configure sharding for some specific MongoDB collections when the app is being deployed on a fresh cluster. The application is using the Lift framework and basically every sharded collection is mapped to a MongoRecord class extending a particular "ShardedCollection" trait. I need to call a particular method on those classes in order to get their collection name.
So the first step is to find in the code those specifics classes and for that I use ClassUtil . Then I need a way to instantiate them and for that I thought that java reflection should be able to do it. It's working but only if those classes do not belong to an outer class.
The configuration in this specific edge case is like:
class X {
class Y extends ShardedCollection {
}
}
So after reading some documentation I found that I had to call YConstructor.newInstance(XObject), newInstance taking as a first argument an XObject (as an instance of X) When Y is an inner class of X. My strategy is to recursively instantiate the enclosing classes until I'm getting the one that has the ShardedCollection trait.
The problem arise when X is no more a class but a trait, and then there is no constructor that I can use for it, but I still need to feed an XObject to newInstance .. Tricky :(
To be very concise from the java doc
If the constructor's declaring class is an inner class in a non-static context, the first argument to the constructor needs to be the enclosing instance
What do I do when the enclosing "thing" is a trait ? (assuming that I can't modify anything in the code base)
Related
I have read how companion and singleton objects can be used to keep static methods, which makes sense. My question is how is this object made or instantiated it? I have read from some sources on how Objects are instances of the class if used as companion objects while others say they are not instances of the class. Then how are the objects existing or being made? Plus the Object would be same class data type I suppose?
My question is how is this object made or instantiated it?
[…]
Then how are the objects existing or being made?
You don't know, shouldn't know, and can't know.
The Scala Language Specification says that they exist. The Scala Language Specification does not say how they are instantiated. Every implementor is free to implement them however they want.
For example, ECMAScript has object literals, so for Scala.js, there is no need for them to be an instance of any class at all. Scala-native is not dependent on any platform, so it can do whatever it wants. Scala-JVM needs to comply with the restrictions of the JVM, where every object needs to be an instance of a class. In Scala-JVM, every singleton object Foo is an instance of a JVM class named Foo$.
Plus the Object would be same class data type I suppose?
The type of a singleton object Foo is the singleton type Foo.type. It's not a class.
I have read from some sources on how Objects are instances of the class if used as companion objects while others say they are not instances of the class.
Instead of reading "some sources", it's much better to just read the source: the Scala Language Specification, specifically section 5.3.2 Case Classes:
A case class definition of 𝑐[tps](ps1)…(ps𝑛) with type parameters tps and value parameters ps implies the definition of a companion object, which serves as an extractor object. It has the following shape:
object 𝑐 {
def apply[tps](ps1)…(ps𝑛): 𝑐[tps] = new 𝑐[Ts](xs1)…(xs𝑛)
def unapply[tps](𝑥: 𝑐[tps]) =
if (x eq null) scala.None
else scala.Some(𝑥.xs11,…,𝑥.xs1𝑘)
}
Each object has its own class, but you can't access the class directly. This class has a constructor without parameters which is called automatically when it's loaded and creates the only instance.
Objects are instances of the class if used as companion objects
Either you misunderstood or you really shouldn't trust these sources. It's possible for a companion object to extend the trait/class it's companion to, but not at all common.
Companion objects are not instances of the class they're companion of, think of them more like a collection of utility methods. If you're familiar with Java - all the method, that you made static in Java (hence they don't belong to a particular instance, but to class in general) would go to Companion object in Scala. Also, companion objects have access to classes private values.
Objects are lazily initialized for you, you don't need to know when and how exactly are they created, just if you call a function from an object - it will be created for you, and there will be only one instance of it.
I am wondering if there is a way to get the quick documentation in IntelliJ to work for the class construction pattern many scala developers use below.
SomeClass(Param1,Parma2)
instead of
new SomeClass(param1,Param2)
The direct constructor call made with new obviously works but many scala devs use apply to construct objects. When that pattern is used the Intelij documentation look up fails to find any information on the class.
I don't know if there are documents in IntelliJ per se. However, the pattern is fairly easy to explain.
There's a pattern in Java code for having static factory methods (this is a specialization of the Gang of Four Factory Method Pattern), often along the lines of (translated to Scala-ish):
object Foo {
def barInstance(args...): Bar = ???
}
The main benefit of doing this is that the factory controls object instantiation, in particular:
the particular runtime class to instantiate, possibly based on the arguments to the factory. For example, the generic immutable collections in Scala have factory methods which may create optimized small collections if they're created with a sufficiently small amount of contents. An example of this is a sequence of length 1 can be implemented with basically no overhead with a single field referring to the object and a lookup that checks if the offset is 0 and either throws or returns its sole field.
whether an instance is created. One can cache arguments to the factory and memoize or "hashcons" the created objects, or precreate the most common instances and hand them out repeatedly.
A further benefit is that the factory is a function, while new is an operator, which allows the factory to be passed around:
class Foo(x: Int)
object Foo {
def instance(x: Int) = new Foo(x)
}
Seq(1, 2, 3).map(x => Foo(x)) // results in Seq(Foo(1), Foo(2), Foo(3))
In Scala, this is combined with the fact that the language allows any object which defines an apply method to be used syntactically as a function (even if it doesn't extend Function, which would allow the object to be passed around as if it's a function) and with the "companion object" to a class (which incorporates the things that in Java would be static in the class) to get something like:
class Foo(constructor_args...)
object Foo {
def apply(args...): Foo = ???
}
Which can be used like:
Foo(...)
For a case class, the Scala compiler automatically generates a companion object with certain behaviors, one of which is an apply with the same arguments as the constructor (other behaviors include contract-obeying hashCode and equals as well as an unapply method to allow for pattern matching).
I understand that using something like
case class private A()
new A()#This will be a invalid call as A is private
But what I do not understand that as from an implementation perspective, what advantage does this provide while coding? Because calling A() twice will give 2 instances of the class anyways. If this syntax is not used to prevent instantiation like Java, then why would I want to not let someone instantiate my class using new?
Marking a case class constructor private is useless. As you've notices, case classes get a synthetic companion object with an apply method whose implementation is simply a call to the actual constructor.
Scala case classes have been designed to just "classes + the case modifier", meaning that everything that works on classes also works on case classes, which also include the (pointless) ability to specify access modifiers on the constructor.
I am unable to understand how to work with nested classes in Scala esp when I encountered the error below:
class Action {
val entityModelVar = new EntityModel
}
class EntityModel {
class EntityLabel {
....
}
}
The above code-snippet gives an idea about my class structure. Here's two code blocks that puzzle me on how they work.
val actionList=Array[Action](Action1,Action2)
..
val newLabels=actionList(i).test(doc)
actionList(i).retrain(newLabels) //error pointed here
**Error: type mismatch:
found : Seq[a.entityModelVar.EntityLabel]
required : Seq[_13.entityModelVar.EntityLabel] where _13:Action**
However, the following code compiles without any error:
//This works fine
val a=actionList(i)
val newLabels=a.test(doc2)
a.retrain(newLabels)
Also, here is the definition of the retrain function:
def retrain(labels:Seq[entityModelVar.EntityLabel])={
entityModelVar.retrain(labels)
}
and the signature of EntityModel.retrain function:
def retrain(testLabels:Seq[EntityLabel]):Unit
The problem is that the inner class has got to belong to the same instance of the outer class. But is actionList(i) guaranteed to be the same instance between two calls? The compiler doesn't know for certain (maybe another thread fiddles with it? who knows what apply does anyway?), so it complains. The _13 is its name for a temporary variable that it wishes were there to assure that it is the same instance.
Your next one works because the compiler can see that you call actionList(i) once, store that instance, get an inner class from it and then apply it.
So, moral of the story is: you need to make it abundantly obvious to the compiler that your inner class instances match up to their proper outer class, and the best way to do that is to store that outer class in a val where it can't change without you (or the compiler) noticing.
(You can also specify types of individual variables if you break up parameter blocks. So, for instance: def foo(m: EntityModel)(l: m.EntityLabel) would be a way to write a function that takes an outer class an an inner one corresponding to it.)
If I create a singleton object Main with no companion class, is there any way to get the class of that singleton? classOf[Main] gives an error: "not found: type Main".
As it's an instance of a class, you can use the method Main.getClass to pull this one off.
Behind the scenes, the JVM knows that Main is an instance of a class named Main$, and this can be accessed via Java reflection methods if necessary.
Having said all of that, there's usually very little need for reflection in Scala anyway, so you shouldn't really need this unless you're just after an interesting bit of theory.
Singleton objects, aka modules, do not have a "class" as you cannot inherit from them. Think of singleton and class as opposite notions.
They do have a type though:
object Main
def test(a: Main.type): Unit = println("Got: " + a)
test(Main)