Scala - How to get constructore fields values in reflection? - scala

I'm pretty new to scala and struggling a bit with reflection.
Given the below class:
class Person (name: String) {
.....
}
and the given instance:
val p = new Person ("MyName")
How can i retrieve the value "MyName" in reflection?
BTW - I tried with java reflection using getClass.getDeclaredFields(), but without luck...
Thanks!

name is not a member of the class in your example, it's just a function parameter of the constructor. The difference in scala in rather subtle, because the whole class is defined inside the constructor body, so, it is, effectively, a closure, and you can use the parameters everywhere, but still, there is a difference.
class Person(val name: String) or class Person(var name: String) declares a class with an instance member (either final or writable) name.
class Person(name: String) has no instance variables, name is just a parameter to the constructor.
Case classes are special, as they treat all constructor parameters as vals by default, this is "syntactic sugar": case class Person(name: String) really means `case class Person(val name: String).

I think you should add modifier var or val when defining constructor.
i.e,
class Person (var name: String) {
.....
}
and to retrieve value "MyName", you can do,
val p= new Person("MyName");
and Name is: p.name

Related

private keyword has different meaning on class definition

I think I had a good understanding of Scala till I find myself in this simple scenario
sealed abstract case class Name private(name: String)
object Name {
def make(name: String): Option[Name] =
if (name.nonEmpty) Some(new Name(name) {}) else None
}
my question is about the private modifier for the class.
If I use it like this, everything works, but if I move the private keyword at the start, something like
private sealed abstract case class Name(name: String) it doesn't compile becuase gives me the following error
private class Name escapes its defining scope as part of type
Option[example.package.Name]
where example.package is the package object I'm working in.
I think I need some clarification because I'm not sure what's happening here
In
sealed abstract case class Name(name: String)
Name effectively denotes both
the name of the class
the default constructor for that class
sealed abstract case class Name private(name: String)
declares that the class is public, but the constructor is private (i.e. can only be called from within that class or its companion object).
private sealed abstract case class Name(name: String)
declares that the class is private (which implies that the constructor is also private).
This code compiles with no error:
private sealed abstract case class Name(name: String)
The problem is that you are then returning a value that contains a public value of this class, so the definition is leaking out and it isn't really private. You need to make sure that all references to Name are also private.
The first syntax marks the constructor as private;
sealed abstract case class Name private(name: String)
This means that the constructor can only be called from inside the Name companion object. So this is not allowed
val name = new Name("name") // constructor Name in class Name cannot be accessed

what's the difference between these classes in Kotlin?

I'm a beginner in Kotlin!
Can we explain the difference between these classes in Kotlin
class Person(val name: String, val age: Int)
class Person(name: String, age: Int)
class Person(var name: String,var age: Int)
And how I add getter and setter for data class in Kotlin?
First you should try to read the difference in the manual:
https://kotlinlang.org/docs/reference/data-classes.html
https://kotlinlang.org/docs/reference/classes.html
But lets try to explain this:
class Person(val name: String, val age: Int)
The Kotlin compiler will generate for both constructor arguments corresponding fields storing the values and will generate respecting getters. The values are immutable because of the keyword val so there will not be any setters.
class Person(name: String, age: Int)
The arguments are only passed to the constructor but not stored as fields. So there will also be no getters and setters.
class Person(var name: String, var age: Int)
Like in the first example the values are stored in generated fields. But the values are mutable because of the keyword var so the compiler will generate getters and setters.
data is an additional (optional) keyword to put in front of the class declaration. This will in addition to the getters and setters generate a toString method printing the values of all attributes with their names and a hashCode method taking every value into account. As getters and setters are generated for data classes you don't need to add them manually.
Kotlin is a lot about reducing the manual work required to do by the developer in Java to be done by the compiler of Kotlin.

Scala adding an extra function to a Class

I encountered the following code while checking through a Scala code. I'm finding it difficult to understand what it does.
class Foo(val name: String, val age: Int, val sex: Symbol)
object Foo {
def apply(name: String, age: Int, sex: Symbol) = new Foo(name, age, sex)
}
Does it add a constructor method to the Class Foo which was already defined?
Is it possible to add extra methods to classes which are already defined using this syntax?
Does it add a constructor method to the Class Foo which was already
defined?
It adds syntax sugar to the class. Meaning, you can create an instance of Foo like this:
val foo = Foo()
Instead of
val foo = new Foo()
Is it possible to add extra methods to classes which are already
defined using this syntax?
In that regards, apply is special as the compiler knows it and expands Foo() to Foo.apply. This means that any other method you want to invoke, you'll have to call the Foo static object, but they will not apply to the Foo instance.
If you want to externally add methods to Foo, you can do so via an implicit class:
implicit class RichFoo(foo: Foo) extends AnyVal {
def fooDetails(): String = s"{Name: ${foo.name}, Age: ${foo.Age}"
}
Now you can call it on an instance of Foo:
val f = Foo()
println(f.fooDetails())
In the case, you can think of Foo.apply() as a static method.
Realistically, objects in Scala are implemented as Singleton instances.
Here's the documentation on that.
You can invoke any class or object instance in Scala if it has an apply method. What you're doing here is adding a constructor method to Foo's companion object so that when you call it, it will instantiate an instance of Foo.
It is not possible to add methods to an instance with this method. For that, you might be interested in the Scala Pimp My Library pattern which is implemented using implicits.
// the following are equivalent, given your code above
val x = new Foo("Jason", 29, 'Male)
val y = Foo.apply("Jason", 29, 'Male)
val z = Foo("Jason", 29, 'Male)
Please read about companion object: http://docs.scala-lang.org/tutorials/tour/singleton-objects.html hope this helps
It simplifies object creation for this type. Other way will be to create case class.
Looks like as duplicate to me:
Scala: companion object purpose
This pattern is commonly know as static factory methods. The code you provided is not very useful, but consider these additional factory methods (think of them as "named constructors"):
class Foo(val name: String, val age: Int, val sex: Symbol)
object Foo {
def apply(name: String, age: Int, sex: Symbol) = new Foo(name, age, sex)
def newMaleFoo(name:String,age:int) = new Foo(name,age,'male)
def newPeterFoo(age:int) = new Foo("Peter",age,'male)
}

How to not override a val of a parent class?

please take a look at the following code:
scala> sealed abstract class Person(val name: String)
defined class Person
scala> case class Student(id: Int, name: String) extends Person(name)
<console>:8: error: overriding value name in class Person of type String;
value name needs `override' modifier
case class Student(id: Int, name: String) extends Person(name)
^
This might be a trivial question, but after searching the web for quite some time, I wasn't able to figure out how to simply pass the string that Student's constructor will be provided as name to the Person's constructor. I don't want to override anything. What am I doing wrong?
Thank you very much in advance!
All constructor parameters of a case class are vals. That's the whole point. Roughly speaking, it is what gives you the ability to enjoy the benefits cases classes provide compared to regular classes: copying, extraction, pattern matching, etc.
If you want Student to be a case class, you should override name. Theoretically, you can avoid overriding it by giving the val a different name: case class Student(id: Int, studentName: String) extends Person(studentName) - this works, but just doesn't make very much sense - you end up having two different member vals whose values are always identical.
Alternatively, if there is an actual reason why you don't want to override name (I can't imagine what one could possibly be, but if ...), then Student should not be a case class: class Student(val id: Int, name: String) extends Person(name).

Extract scala case class field

Given the following class: case class Test(id: Long, name: String) {
val details = Map("size" -> 54)
}
How do i extract details without instantiating the class? I Know how to extract the id and the name using Scala reflection but can't figure out how to extract what i need.
There are no static members in Scala. Instead, when you have data that should be statically available from arbitrary code without instantiating the enclosing class, we usually define objects with that data.
object Test {
val Details = Map("size" -> 54)
}
case class Test(id: Long, name: String) {
val details = Test.Details
}
Note the case of the literal Details - unlike Java, there's a convention in Scala to name constants in CamelCase, starting with an uppercase letter.