kotlin: "unresolved reference" in sceondary constructor - kotlin

i am very new to kotlin, and maybe this might be a silly question but why using a variable defined in a secondary parameter gives an error of "unresolved reference" when i try to print it while the same does not happen in case of primary constructor
fun main(args: Array<String>){
var stud= Student("Yash", 10)
}
class Student(name: String) {
init {
println("name is $name")
}
constructor(n: String, Id: Int): this(n) {
println("name is $n")
println("id is $id")
}
}

Parameter id is small letter,but you are try to print capital letter Id, change like this its working now
constructor(n: String, id: Int)
fun main(args: Array<String>){
var stud= Student("Yash", 10)
}
class Student(name: String) {
init {
println("name is $name")
}
constructor(n: String, id: Int): this(n) {
println("name is $n")
println("id is $id")
}
}

Related

Passing null value to Kotlin method with non nullable default arguments

I am new to Kotlin and I found one of the features which Kotlin differs from Java is method default arguments.
https://kotlinlang.org/docs/functions.html#default-arguments
I am creating a simple Kotlin application which passes null values to a method with 2 non nullable default arguments, which results in a compilation error - Type mismatch: inferred type is String? but String was expected).
fun greet(firstName: String = "Hello", lastName: String = "world") {
println("${firstName} ${lastName}")
}
fun main(args: Array<String>) {
greet(args.getOrElse(0) { null }, args.getOrElse(1) { null })
}
One workaround is to change the method arguments to nullable, but the cleaniness of the original method is lost.
fun greet(firstName: String?, lastName: String?) {
val firstName2 = firstName ?: "Hello"
val lastName2 = lastName ?: "world"
println("${firstName2} ${lastName2}")
}
fun main(args: Array<String>) {
greet(args.getOrElse(0) { null }, args.getOrElse(1) { null })
}
If I have to keep the original method signature, I can think of below alternative solutions.
Duplicate the default argument definitions in method signature and method caller
fun greet(firstName: String = "Hello", lastName: String = "world") {
println("${firstName} ${lastName}")
}
fun main(args: Array<String>) {
greet(args.getOrElse(0) { "Hello" }, args.getOrElse(1) { "world" })
}
Separate method calls based on the number of arguments
fun greet(firstName: String = "Hello", lastName: String = "world") {
println("${firstName} ${lastName}")
}
fun main(args: Array<String>) {
when (args.size) {
0 -> greet()
1 -> greet(args[0])
2 -> greet(args[0], args[1])
}
}
All 3 solutions print Hello world when no argument is supplied. I am wondering if there are other better alternative solutions.
Rather than using default arguments, it's better to be explicit and validate your inputs, then you can avoid the ambiguity:
fun greet(firstName: String, lastName: String) = println("$firstName $lastName")
fun main(args: Array<String>) {
require(args.size == 2) { "Must supply two arguments" }
val (arg1, arg2) = args
greet(arg1, arg2)
}

Parcelable in Kotlin

When I auto Parcelable my class parcel.readString() and parcel.readString() are underlined red even though my variables are in String format . Here is my code
import android.os.Parcel
import android.os.Parcelable
class adel constructor(var lel : String, var skl: String) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readString()
) {}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(lel)
parcel.writeString(skl)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<adel> {
override fun createFromParcel(parcel: Parcel): adel {
return adel(parcel)
}
override fun newArray(size: Int): Array<adel?> {
return arrayOfNulls(size)
}
}
}
Since you are in Kotlin, you can skip the implementation and instead install a nice feature. Just add this in build.gradle:
androidExtensions {
experimental = true
}
Then in you class:
import kotlinx.android.parcel.Parcelize
#Parcelize
data class Adel(var lel : String, var skl: String) : Parcelable
And you are done. Note that you will have a lint error. Just ignore it.
parcel.readString()
is nullable, replace with
parcel.readString().orEmpty()

How to pass is operator parameter through function in Kotlin

val k = " asdfasdf "
fun test() {
if(k is String) {
// Do something
}
}
So, how do I pass that String through the function calls
eg:
fun test(xxxx) {
if(k is xxxx) {
// do something
}
}
Like this:
inline fun <reified T> testType(k: Any) {
if(k is T) {
println("is a ${T::class.simpleName}")
} else {
println("is not a ${T::class.simpleName}")
}
}
Call it like this:
test<String>("Hello") // is a String
test<String>(1) // is no String
Here some further reading.
There are two possibilities, depending on your needs.
1. Use inline and a reified type parameter
You can use the reified keyword on the type parameter in combination with an inline function:
inline fun <reified T> test(k: Any) {
if (k is T) {
println("k is a T!")
}
}
See the documentation on reified.
2. Use KClass<T>
If you do not want to or cannot make your function inline you can use a KClass parameter:
fun <T : Any> test(k: Any, type: KClass<T>) {
if (type.isInstance(k)) {
println("k is a T!")
}
}
You can either use a predicate, e.g.:
fun testIt(predicate: (Any?) -> Boolean) {
if (predicate(k)) {
println("matches!")
} else println("nope")
}
and call it as follows:
testIt { it is String }
testIt { it is Int }
Or you can use a reified type:
inline fun <reified T> testIt() {
when (k) {
is T -> println("matches!")
else -> println("nope")
}
}
and call it like:
testIt<String>()
testIt<Int>()
For simplicity I kept your current variable inside the testIt-method... you may want to redesign that ;-)
I basically assumed a member variable as follows: var k : Any? = null
inline fun <reified T> isType(obj: Any): Boolean {
return obj is T
}
fun main(args: Array<String>) {
val test = "This is a String"
if (isType<String>(test)) {
println("Success")
} else {
println("Failure")
}
}

Kotlin - get name from lambda expression

I want to get the name of a parameter passed into a lambda expression in Kotlin. In C# I would use an Expression<Func<T, ...>> to get the parameter name, but I'm not sure whether this is possible in Kotlin
import java.util.*
fun main(args: Array<String>) {
val foo = Foo<Model>()
foo.bar { it.age }
// Should print "age"
}
data class Model(val id: UUID, val name: String, val age: Int)
class Foo<T> {
fun bar(expression: (x: T) -> Any) {
println(/*The name of the parameter*/)
}
}
Is this possible in Kotlin?
If you want to pass around properties and print their names, you can do it by using KProperty:
fun main(args: Array<String>) {
val foo = Foo<Model>()
foo.bar(Model::age)
}
class Foo<T> {
fun bar(p: KProperty<*>) {
println(p.name)
}
}

How to get names and values of method's parameters?

Is there possibility to get names of method's parameters inside method code? Can anyone show example of it?
I found only this solution at this time, but dislike it..:
class Greeter() {
fun greet(name: String) {
val c = Greeter::class;
for (m in c.memberFunctions) {
if (m.name == "greet") {
val p = m.parameters
println(p.toString())
}
}
println("Hello, ${name}");
}
}
fun main(args: Array<String>) {
Greeter().greet("UserName")
}
update: i found another solution, but now i have one more question:
How to get pairs of ParamName, ParamValue at function greet?
class Greeter() {
fun greet(name: String) {
val p = Greeter::greet.parameters
println(p.toString())
println("Hello, ${name}");
}
}
fun main(args: Array<String>) {
Greeter().greet("UserName")
}
Parameter names are available through the KParameter.name property:
class Greeter() {
fun greet(name: String) {
val p = Greeter::greet.parameters
println("Hello, ${p[0].name}")
}
}
Parameter values, on the other hand, cannot be obtained reflectively easily on JVM.