Kotlin constructors: primary and secondary - constructor

Just have started with Kotlin, where you can have a primary constructor and secondary ones. The question may sound simple, but I couldn't find an answer to it (I've read the "constructors" section in the documentation
) - why?
Basically, I'm trying to understand what is the idea behind being primary and secondary. And what is the difference in how they are used (seems like there's not, so why the separation)?

The are various syntactic differences, clearly. But a major conceptual difference is that all secondary constructors ultimately delegate to the primary constructor.
The way I think about this is that the primary constructor is the canonical interface for creating an object, and secondary constructors are like static helpers for transforming other argument sets to comply with this interface.*
* Please note this is a personal interpretation, not backed up with official docs in any way!

Primary constructor
A Kotlin class can only have one primary constructor.
Primary constructor provide a simple way to initialize the member properties of a class.
It takes a list of comma-separated parameters and declared just after the class name as a part of the header.
// How to declare a primary constructor
class Student constructor(
firstName: String,
lastName: String
) {
}
// We can omit constructor keyword if the primary constructor
// does not have any annotations or visibility modifiers
class Student(
firstName: String,
lastName: String
) {
}
fun main() {
val student1 = Student("Helen", "trump")
}
Since primary constructor in Kotlin has constrained syntax, it is defined only to declare class properties, it doesn't accept any logic or code. So, to fill this gap, Kotlin provides a flexible concept of init block in which we can add more custom code to perform some logic!
class Student(
firstName: String,
lastName: String
) {
init {
println("Welcome to the student profile")
}
}
These initializer block is executed after the primary constructor is called and before any secondary constructors.
Secondary constructor
A Kotlin class can have one or more secondary constructors.
They must be prefixed by the keyword constructor.
We can't declare class properties inside secondary constructor the same way we do in primary constructor.
Every secondary constructor must explicitly call the primary constructor. We can do that by using this keyword.
class Pizza constructor (
var crustSize: String,
var crustType: String,
val toppings: MutableList<String> = mutableListOf()
) {
// secondary constructor (no-args)
constructor() : this("SMALL", "THIN")
// secondary constructor (2-args)
constructor(crustSize: String, crustType: String) : this(crustSize, crustType, mutableListOf<String>())
override fun toString(): String = "size: ${crustSize}, type: ${crustType}, toppings: ${toppings}"
}
fun main(args: Array<String>) {
val p1 = Pizza()
val p2 = Pizza("LARGE", "THICK")
val p3 = Pizza("MEDIUM", "REGULAR", mutableListOf("CHEESE", "PEPPERONI"))
println(p1)
println(p2)
println(p3)
}
Output:
size: SMALL, type: THIN, toppings: []
size: LARGE, type: THICK, toppings: []
size: MEDIUM, type: REGULAR, toppings: [CHEESE, PEPPERONI]
Reference
https://kotlin-quick-reference.com/102b-R-secondary-constructors.html

the kotlin primary constructor help you to write the compact code :
you can write class without body, e.g:data class, for example:
data class Data(val value:String)
if you don't have any annotation on constructor, then the keyword constructor can be ommitted. a negative example:
class Foo #Annotation constructor()
it make the inherit simply, for example:
open class Bar(val value: String);
class Primary(value: String, other: String) : Bar(value)
class Secondary : Bar {
constructor(value: String, other: String) : super(value)
}
it can using delegations by keyword by, but secondary constructor can't uses.
interface Rule {
fun apply(value: String): Int
}
open class Policy(rule: Rule) : Rule by rule;

Related

Get SerializedName param from child class in Kotlin

I am trying to parse an API response mainly constructured like this:
{
"ApiFunc1":{
"SomeData1":"SomeValue1",
"SomeData2":"SomeValue2",
"SomeData3":"SomeValue3"
}
}
{
"ApiFunc2":{
"SomeData4":"SomeValue4",
"SomeData5":"SomeValue5",
"SomeData6":"SomeValue6"
}
}
.
.
.
I created a base class as follows:
class Model_BaseResponse<TResponse> : Serializable {
#SerializedName("ErrorMessage")
var errorMessage: String? = null
#SerializedName("value")
var data: TResponse? = null
}
Each ApiFunc returns different data. I want to create a base class where data: TResponse's #SerializedName("ApiFunc1") or #SerializedName("ApiFunc2") can be set in child class. Is there any way to that? I do it in regular way, defining the
#SerializedName("value")
var data: TResponse? = null
in every child class. Just been curious about that. Thanks in advance for any idea.
An annotation like SerializedData requires its arguments to be compile-time constants. Having a look at what "compile-time constant" means in Kotlin reveals:
Properties the value of which is known at compile time can be marked as compile time constants using the const modifier. Such properties need to fulfil the following requirements:
Top-level or member of an object
Initialized with a value of type String or a primitive type
No custom getter
Such properties can be used in annotations:
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
#Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }
I believe the first requirement "Top-level or member of an object" cannot be fulfilled for your use case.

How are secondary kotlin constructor variables passed in?

I am looking at the solution for the gigasecond exercism exercise for Kotlin: http://exercism.io/exercises/kotlin/gigasecond/readme. I can understand how it needs two two constructor because LocalDate and LocalDateTime arguments are passed in when creating the class. What I don't understand is how the below secondary class constructor variables are passed in and used in the class. It seems like the calculation only happens when LocalDateTime arguments are passed in, as calculation is only done with dobWithTime. What magic is happening here ?
data class Gigasecond(val dobWithTime: LocalDateTime) {
constructor(dateOfBirth: LocalDate) : this(dateOfBirth.atStartOfDay())
val date: LocalDateTime = dobWithTime.plusSeconds(1000000000)
}
The secondary constructor just forwards the call to primary constructor with the : this() syntax, while creating the required LocalDateTime object from the LocalDate that it received as its parameter.
You could think of the secondary constructor as a function that does the following:
fun createGigaSecond(dateOfBirth: LocalDate): Gigasecond {
return Gigasecond(dateOfBirth.atStartOfDay())
}
Except it gets to use the usual constructor syntax instead, and so it can be called as Gigasecond(dataOfBirth) instead of createGigaSecond(dateOfBirth).
From the official documentation about secondary constructors:
If the class has a primary constructor, each secondary constructor needs to delegate to the primary constructor, either directly or indirectly through another secondary constructor(s). Delegation to another constructor of the same class is done using the this keyword.
This is what's happening here.

Kotlin: Generic function as return type?

In Kotlin, is it possible to declare a generic function type as the return type of a function?
What I want to achieve would look like this in Java:
interface Factory {
static Factory INSTANCE = new FactoryImpl();
<T> T create(String name, Class<T> type);
}
class PrefixedFactory implements Factory {
private final String prefix;
PrefixedFactory(String prefix) {
this.prefix = prefix;
}
#Override
public <T> T create(String name, Class<T> type) {
return Factory.INSTANCE.create(prefix + name, type);
}
}
(Note that in the example I access the Factory instance using the static field to avoid passing a generic function as a parameter, which would present its own problems in Kotlin).
I would like convert the prefixer to a kotlin function, but it seems to be impossible to declare a generic function as the return type:
fun prefixer(prefix: String): <T> (String, KClass<T>) -> T { TODO() }
This of course does not compile. It seems to me that this is a limitation compared to Java's functional interfaces. Is there a way to accomplish this, or a workaround?
(Edit) Clarification
I want the actual result function to be generic. If I do
fun <T: Any> prefixer(prefix: String): (String, KClass<T>) -> T { TODO() }
as the current answers suggest; I don't get a generic function, instead I get (String, KClass<Foo>) -> Foo if I call prefixer<Foo>(""). So that function can only be called with Foo, while the factory function prefixer in that case is generic, the result is not. I hope that clears up the misunderstandings.
My use case is in a Gradle plugin, where I wrote a helper method similar to this one that applies some defaults to each task created:
val myPrefix = "..."
val project: Project = <from context>
fun <T: Task> String.task(type: KClass<T>, doConfig: T.() -> Unit) {
project.tasks.create("$prefix$this", type.java, { it.doConfig() })
}
Note that the project comes in as closure. Now I want to reuse that helper in a different plugin, so I would like to create this function using a factory for different project instances.
You're doing it almost correctly. You only need to define the generic part at the prefixer function directly.
fun <T: Any> prefixer(prefix: String): (String, KClass<T>) -> T { TODO() }
Depending on you actual implementation, you could have a look at the reified keyword.
No, it isn't possible (as far as I know). The technical term for such a type is "higher-kinded type" and very few languages support them, on JVM I only know of Scala.
If someone asked me the same question without having an interface like Factory, I'd suggest creating exactly this interface as a workaround.
The following line does compile:
fun <T : Any> prefixer(prefix: String): (String, KClass<T>) -> T = TODO()
First, the generic deceleration should be right after the fun keyword.
Then it has has to be declared as type Any. The default is Any? but KClass only takes Any.
Although I was disappointed to read #Alexey's answer, I found a more streamlined workaround taking advantage of Kotlin's operators. The following makes it look more like a lambda when used:
private class Prefixer(private val: String) {
operator fun <T> invoke(name: String, type: Class<T>): T {
TODO()
}
}
To use it:
val createMy = Prefixer("MyPrefix")
val result = createMy("Configuration", Configuration::class.java)
Feel free to replace with KClass where necessary. I was actually using this for a slightly different purpose.

Angular 2: How to preserve class methods on deserialization?

Let's say I have a class Foo:
export class Foo {
name: string;
printName(): void {
console.log(this.name);
}
}
Now the problem is that when my FooService gets a Foo from my backend as JSON and creates a Foo object out of it, it doesn't have printName() because there's no such thing in the JSON object.
How should I arrange this (in the context of Angular 2)? Do I have to create my methods outside the class so that they just take a Foo as an argument?
In Java, for example, it's perfectly fine that DTO's have methods.
Usually you only transfer an object with the values over http not a class instance. You have to create the class instance yourself.
export class Foo {
constructor(name: string) {}
printName(): void {
console.log(this.name);
}
}
// data deserialized by angular from the request
let data = { name: 'John' };
let foo: Foo = new Foo(data.name);
If it helps you can make interfaces for the data you receive from the server and pass that to the constructor of the Foo class.
Note: keep in mind that there is no type casting in TS.
If you are doing something like
let foo: Foo = <Foo> data;
It is a type assertion, you just tell the compiler that data is of type Foo it doesn't do anything to the data object.

How to decorate an immutable object graph from scala case classes

I'm reading structured JSON, using Play Frameworks' JSON Reads to build up an object graph with case classes.
An example:
case class Foo (
id: Int,
bar_id: Int,
baz_id: Int,
x: Int,
y: String
)
{
var bar: Bar = null
var baz: Baz = null
}
After building the Foo, I must come back later and decorate it by setting bar and baz. Those are defined in other JSON files and only known when all parsing is complete. But this means Foo can't be immutable.
What is the "right" way in Scala to make an immutable object, and then a decorated version of it, without repeating every field of Foo multiple times, over and over?
I know several ways that feel wrong:
make "bar: Option[Bar]" and "baz: Option[Baz]" case class parameters, and then I can use "copy" to make new versions of the Foo class with them set to something; but then I have to check them every single time they're accessed - inefficient, unsafe, not able to make a DecoratedFoo that just is guaranteed to have the right structure
make a second case class that is a copy-paste of all the structure in the first, but adding the two extra decorated parameters - but this means echoing the entire parameter list in the definition, and again when creating instances of it
Case class inheritance is apparently controversial, and in any case also appears to require me to repeat every single parameter anyway, in the subclass constructor?
Make a non-case superclass listing the common case class parameters. Then extend it in the case class. But this would seem to still require repeating every single parameter in the subclass constructor as well.
I see blogs with people talking about this problem and using reflection at runtime to populate the base attributes of their decorated copies - this avoids echo but now you have no type safety, specifying attribute names as strings, overhead, etc...
Surely Scala must have a way to let people compose more complicated immutable objects out of simpler ones without having to copy each and every part of them by hand?
You could introduce a new trait for the processed types, a class that extends that trait, and an implicit conversion:
case class Foo(bar: Int)
trait HasBaz {
val baz: Int
}
class FooWithBaz(val foo: Foo, val baz: Int) extends HasBaz
object FooWithBaz {
implicit def innerFoo(fwb: FooWithBaz): Foo = fwb.foo
implicit class RichFoo(val foo: Foo) extends AnyVal {
def withBaz(baz: Int) = new FooWithBaz(foo, baz)
}
}
So then you can do:
import FooWithBaz._
Foo(1).withBaz(5)
And, although withBaz returns a FooWithBaz, we can treat the return value like a Foo when necessary, because of the implicit conversion.
Combining Option and type parameters you can flag your case class, and track whether the processed fields are empty, statically:
import scala.language.higherKinds
object Acme {
case class Foo[T[X] <: Option[X] forSome { type X }](a: Int,
b: String,
c: T[Boolean],
d: T[Double])
// Necessary, Foo[None] won't compile
type Unprocessed[_] = None.type
// Just an alias
type Processed[X] = Some[X]
}
Example use case:
import Acme._
val raw: Foo[Unprocessed] = Foo[Unprocessed](42, "b", None, None)
def process(unprocessed: Foo[Unprocessed]): Foo[Processed] =
unprocessed.copy[Processed](c = Some(true), d = Some(42d))
val processed: Foo[Processed] = process(raw)
// No need to pattern match, use directly the x from the Some case class
println(processed.c.x)
println(processed.d.x)
I used this once in my current project. The main problem I encountered is when I want Foo to be covariant.
Alternatively, if you don't care about the bound on T:
case class Foo[+T[_]](a: Int, b: String, c: T[Boolean], d: T[Double])
then you can use Foo[Unprocessed] or Foo[Processed] when you need a Foo[Option].
scala> val foo: Foo[Option] = processed
foo: Acme.Foo[Option] = Foo(42,b,Some(true),Some(42.0))
One other strategy might be to create yet another case class:
case class Foo(
id: Int,
bar_id: Int,
baz_id: Int,
x: Int,
y: String
)
case class ProcessedFoo(
foo: Foo,
bar: Bar,
baz: Baz
)