Is it worth, to control the visibility of case class that represent value object ? If so, is a visibility modifier on the case class enough, or using an explicit companion object, and a private constructor, would be better ?
Version 1:
case class MyClass private/protected/private[] {}
Version 2:
case class MyClass private
object MyClass {
def apply = {
new MyClass
}
}
In sum, the question could be summarize as how to deal with value object in scala.
I personally want to enforce the no new, so that is i want to change something in the creation of the object, I can do it at any time. That is, by simply adding a companion object when necessary.
A visibility modifier on the case class constructor does not propagate to the companion object, so creating one yourself by hand with the exact same apply method is unnecessary.
You can verify this yourself trivially:
$ scala
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_37).
Type in expressions to have them evaluated.
Type :help for more information.
scala> case class X private () {}
defined class X
scala> new X
<console>:10: error: constructor X in class X cannot be accessed in object $iw
new X
^
scala> X()
res1: X = X()
Note that just plain X is the name of the companion object. You can't get a new X by naming the companion object; that won't call its apply method even if a no-argument apply exists. So you can't omit the empty parameter list ().
The above is all true in the REPL, but compiled code fails.
Related
Let's say I want an integer that supplies a square method.
Kotlin:
fun Int.square() = this * this
usage:
println("${20.square()}")
doc:
Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on variables of this type.
We would like to emphasize that extension functions are dispatched statically
My expectation would've been that they simply add it to the member functions of the extended class during compilation, but that is what they explicitly deny, so my next thought was it could be "sort of" like scala implicits.
Scala:
object IntExtensions{
implicit Class SquareableInt(i:Int){
def square = i*i
}
}
usage:
import IntExtensions._
and then
println(f"${20.square}")
doc:
An implicit class is desugared into a class and implicit method pairing, where the implciit method mimics the constructor of the class.
The generated implicit method will have the same name as the implicit class.
But scala implicits create a new class, that would disable the usage of this.
So ... how IS it that Kotlin extends classes? "Make callable" isn't telling me much.
In your case Kotlin just create simple utils-class with name "filename"Kt and static method "int square(int x)" (java pseudo-code)
From Java it look something like this
// filename int-utils.kt
final class IntUtilsKt {
public static int square(int x) {
return x * x;
}
}
And after this all calls to
val result = 20.square()
will be transformed (on byte-code level) to
val result = IntUtilsKt.square(20);
P.S.
You can see it yourself using IDEA action "Show Kotlin byte-code"
I'm new to both Scala and Akka and have been following this tutorial. I came across the following and wondering what exactly this syntax does/mean?
import akka.actor.Props
val props1 = Props[MyActor] //Not sure what this means???
val props2 = Props(new ActorWithArgs("arg")) // careful, see below
val props3 = Props(classOf[ActorWithArgs], "arg")
I'm not sure what the line commented with //Not sure what this means does? It seems like a generic trait that gives a parameterised type. If I look at the source code, akka.actor.Props is defined as an Object that extends the trait AbstractProps. However, AbstractProps is not defined with a type parameter i.e. AbstractProps[T]. Can someone explain how that above line works and what it does?
In Scala, any object which implements an apply method can be called without the new keyword, simply by calling MyObject(), which will automatically lookup for it's apply.
If you look at the companion object for Props, you'll see the following method defined:
/**
* Scala API: Returns a Props that has default values except for "creator"
* which will be a function that creates an instance
* of the supplied type using the default constructor.
*/
def apply[T <: Actor: ClassTag](): Props =
apply(defaultDeploy, implicitly[ClassTag[T]].runtimeClass, List.empty)
This apply takes one type parameter and no arguments. T <: Actor means that T, the type you're passing, must extend Actor. That's how Scala knows how to create the object.
Additionally, any method with arity-0 in Scala may drop it's parenthesis. That's how you're seeing Props[MyActor] actually compile, as it is equivalent of Props[MyActor](), which is equivalent to Props.apply[MyActor]().
akka.actor.Props is defined as an Object that extends the trait
AbstractProps
Its also defined as a case class:
final case class Props(deploy: Deploy, clazz: Class[_], args: immutable.Seq[Any])
This is a common pattern in Scala, a class with a companion object. The companion object frequently houses factory methods, and thats what your actually calling in your example.
val props1 = Props[MyActor]
This simply calls apply() of the companion object. You can omit the parentheses in Scala if no arguments are neccessary and apply is a special method that can be invoked directly on the object/instance. Say you have a sequence and want the element at index 1:
val s = Seq("one", "two", "three")
// These two are equivalent
s(1) // -> "two"
s.apply(1) // -> "two"
Ultimately your code can be rewritten as
val props1 = Props.apply[MyActor]()
In Java, while type arguments are erased in runtime, it is possible to find the actual type arguments passed to a superclass:
class Derived extends Base<String> {
// ...
}
ParameterizedType type = (ParameterizedType)Derived.class.getGenericSuperclass();
Type[] args = type.getActualTypeArguments(); // gives {String.class}
While I can use the same Java reflection to Scala class, It does not catch Scala's value types:
class Base[T]
class Derived extends Base[Int]
classOf[Derived]
.getGenericSuperclass
.asInstanceOf[ParameterizedType]
.getActualTypeArguments // gives {Object.class}, not {int.class}
Is it possible to determine the value type used when extending from a generic superclass? I am loading classes from a jar file so it'd be best to achieve this only using a java.lang.Class instance.
In Java reflection you won't be able to obtain Int and other AnyVal types because they are handled specially by the compiler and if they are used generically, they will be represented by Object. However, you can use Scala reflection, and it is wholly possible to go from Java reflection to Scala reflection. Here's how:
import scala.reflect.runtime.universe._
class Base[T]
class Derived extends Base[Int]
object Main extends App {
val rm = runtimeMirror(getClass.getClassLoader) // whatever class loader you're using
val derivedSym = rm.staticClass(classOf[Derived].getName)
val baseSym = rm.staticClass(classOf[Base[_]].getName)
val TypeRef(_, _, params) = derivedSym.typeSignature.baseType(baseSym)
println(s"$derivedSym extends $baseSym[${params.mkString(", ")}]")
}
Unfortunately, unless you know exactly what you are searching for, you will have hard time finding proper documentation. I have found the answer on scala-users mailing list. Scala reflection is still experimental and, AFAIK, it will probably be superseded by a better one in future Scala versions.
Before Scala 2.10 I had
class A {
class B(b: Int) {
}
}
and somewhere in code recreate class B with
val bCtor = bInstance.getClass.getConstructor(classOf[Int])
bCtor.newInstance ...
and everything was fine. It was with signature public A$B(Int)
Now constructor have 2!!! arguments. It has a new signature public A$B(A,Int). What is argument with type A? I don't have access to A class from my function. It there any workaround?
For example newInstance with arguments - It doesn't work anymore for inner class
Be carful not to confuse java inner class with scala path-dependent type
(from the Programming In ScalaBook) :
A path-dependent type resembles the syntax for an inner class type in Java, but there is a crucial difference: a path-dependent type names an outer object, whereas an inner class type names an outer class
So in your case bInstance is related to an aInstance.
My assumption is that aInstance is the object passed as the first parameter to this constructor.
You can use an unconstrained self-type annotation to have a way to refer to the A's version of this even from within B (where this now refers to the B instance).
package rrs.scribble
object OuterInner {
class Outer { oThis =>
class Inner {
def identify { printf("I am %s; I'm inside of %s%n", this, oThis) }
}
val inner = new Inner
}
def oiTest {
val o1 = new Outer
o1.inner.identify
}
}
In the REPL:
Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_37).
scala> import rrs.scribble.OuterInner._
import rrs.scribble.OuterInner._
scala> oiTest
I am rrs.scribble.OuterInner$Outer$Inner#63d0d313; I'm inside of rrs.scribble.OuterInner$Outer#22d1b797
First, adding A as the first constructor argument is also the way it works in Java:
If this Class object represents an inner class declared in a non-static context, the formal parameter types include the explicit enclosing instance as the first parameter.
Second,
What is argument with type A? I don't have access to A class from my function.
If you have a B (as seems from your example), then you can access its enclosing instance (it doesn't seem to be documented officially, and so may change in the future versions of Java):
val aInstance = bInstance.getClass.getDeclaredField("this$0").get(bInstance)
bCtor.newInstance(aInstance, ...)
If you don't, then you can't create a B (without an A), but you shouldn't be able to. What would you expect this code to return?
class A(foo: Int) {
class B {
def bar = foo
}
}
classOf[A#B].getConstructor().newInstance().bar
#evantill is right, the only constructor of B is A$B.<init>(A, Int). So bInstance.getClass.getConstructor(classOf[A], classOf[Int]) works.
I have something like this in scala:
abstract class Point[Type](n: String){
val name = n
var value: Type = _
}
So far so good. The problem comes in a class that extends Point.
case class Input[Type](n:String) extends Point(n){
def setValue(va: Type) = value = va
}
On the setValue line I have this problem:
[error] type mismatch;
[error] found : va.type (with underlying type Type)
[error] required: Nothing
[error] def setValue(va: Type) = value = va
I have tried to initialize with null and null.asInstanceOf[Type] but the result is the same.
How can I initialize value so it can be used in setValue?
You should specify that Input implements Point with the generic type Type because for now, as it is not specified, it is considered as Nothing (I guess the compiler can't infer it from the setValue method). So you have to do the following:
case class Input[Type](n:String) extends Point[Type](n){
def setValue(va: Type) = value = va
}
More information
I answered this question for the compilation error (it does compile on scala 2.9.0.1). Moreover I saw this case class as the implementation for an existing type, like 'Int'. The usage of _ is of course a bad idea in the abstract class, however it is not prohibited, but the _ is not always a null, it is the default value, for exemple: var x:Int = _ will assign the value 0 to x.
Try the following:
package inputabstraction
abstract class Point[T](n:String){
def value: T
val name = n
}
case class Input[T](n:String, value:T) extends Point[T](n)
object testTypedCaseClass{
def test(){
val foo = Input("foo", "bar")
println(foo)
}
}
A simple Application to check that it works:
import inputabstraction._
object TestApp extends Application{
testTypedCaseClass.test()
}
Explanation
The first mistake you are making is case class Input[Type](n:String) extends Point(n){. Point is a typed class, and so when you are calling the superclass constructor with extends Point(n) you need to specify the type of Point. This is done like this: extends Point[T](n), where T is the Type you are planning to use.
The second error is that you are both defining and declaring value:T here: var value: Type = _. In this statement, _ is a value. Its value is Nothing. The scala compiler infers from this that Point[T] is Point[Nothing]. Thus when you attempt to set it to a type in the body of your setValue method, you must set it to Nothing, which is probably not what you want. If you attempt to set it to anything besides Nothing, you will get the type mismatch from above, because value is typed as Nothing due to your use of _.
The third mistake is using var instead of val or def. val and def can be overridden interchangeably, which means that subtypes can override with either val or def, and the scala compiler will figure it out for you. It is best practice to define vals as functions using def in abstract classes and traits, because the initialization order of subtype constructors is a very difficult thing to get right (there is an algorithm for how the compiler decides how to construct a class from its supertypes). TL#DR === use def in supertypes. Case class parameters are automatically generate val fields, which, since you are extending a Point, will create a val value field that overrides the def value field in Point[T].
You can get away with all this Type||T abstraction in Scala because of type inference and the fact that Point is abstract, therefore making value extendable via val.
The preferred way of doing dependency injection like this is the cake pattern, but this example I have provided works for your use-case.