How to access outside data class property from inner enum class? - kotlin

I'm learning Kotlin and got stuck on how to access an outside data class property from an inner enum class. Example code below on what I'm trying to do and the error message:
private data class MyClass(val num: Int) {
val number: Int = this.num
private enum class MyEnum(val elem: String) {
VERTICAL("|"),
HORIZONTAL("—"),
NUMBERS((1..number).joinToString(" ")) // <-- Unresolved reference: number
}
}

Related

How to initialize data to variable with same name as constructor variables?

I have a variable foo:String declared in Kotlin and in constructor I want to pass variables with same name as foo:String but I don't know how to make both variables different from each other as in C# we use this.foo for class variables
I am expecting:
class Product
{
lateinit var productName:String
constructor(productName:String)
{
this.productName = productName
}
}
Please guide me how to do it in Kotlin.
That entire class can be written as just
class Product(var productName: String)
You use this like you used in C#
This sample shows how to do this for primary constructor
class Product{
private val name : String
constructor(name : String) {
this.name = name
}
}
And this is sample for second constructor:
class Product (){
private var name : String = ""
constructor(name : String) : this() {
this.name = name
}
}

How to change return type based on a function input which is a class name?

I have multiple data classes and each class has a corresponding class containing more info. I want to write a function in which I should be able to pass an identifier (table name corresponding to the data class). Based on this identifier, object of the corresponding class should be made, the value changed and this object should be returned as output of the function. I have written a simplified version of it on playground but I am unable to get it to work. Any help is appreciated.
class someClass(
)
class objectForSomeClass(
var value: String
)
class someOtherClass(
)
class objectForSomeOtherClass(
var value: String
)
class doSomething() {
companion object {
val classMap = mapOf(
"someClass" to objectForSomeClass::class,
"someOtherClass" to objectForSomeOtherClass::class,
)
}
// Create a map of class name to a new object based on the class name input
fun dummyFun(className: String, valueInput: String): Map<String, kotlin.Any> {
var returnObject = mutableListOf<Pair<String, kotlin.Any>>()
when(className) {
"SOME_CLASS" -> {
returnObject = mutableListOf<Pair<String, justDoIt.classMap["someClass"]()>>()
}
"SOME_OTHER_CLASS" -> {
returnObject = Map<String, justDoIt.classMap["someOtherClass"]()>
}
}
returnObject[className].value = valueInput
return returnObject
}
}
fun main() {
var obj = doSomething()
var t = obj.dummyFun("SOME_CLASS", "Value to be inserted")
// do something with t
}
Not knowing more about your classes (the ones in your code are not data classes – a data class in Kotlin is a specific type of class) I still think a lot could be simplified down to maybe even this:
fun createObject(className: String, value: String): Any? {
return when (className) {
"SomeClass" -> ObjectForSomeClass(value)
"SomeOtherClass" -> ObjectForSomeOtherClass(value)
// ...
else -> null
}
}
Additionally:
The classMap is not necessary, you can hard-code the cases in the when clause as in my example. There is also no need for reflection, which you would need to create instances from SomeType::class.
With getting rid of classMap you also do not need the companion object holding it anymore, and then you are left with one function for creating instances of your classes, and this function does not have to be in a class. You might put it into a singleton class called object in Kotlin (https://kotlinlang.org/docs/object-declarations.html#object-expressions)
Data classes in Kotlin: https://kotlinlang.org/docs/data-classes.html
You could maybe also replace each class someClass & class objectForSomeClass pair with a class someClass with a companion object.

Kotlin inner class can't resolve extension function declared in outer class

Why inner class in Kotlin can't not access extension function declared in outer class as below:
class A{
val a = "as".foo() // LINE 1
class B{
val b = "as".foo() // LINE 2
}
fun String.foo(){}
}
On LINE 1 extension function is resolved but on LINE 2 the function is not resolved. Wonder why there is such limitation?
This is not an inner class, because you didn't use the keyword inner on it. It is merely a nested class. If you're familiar with Java, it's like a static inner class. Since it is not inner, it does not have any implicit reference to the outer class, and cannot make bare calls to members of the outer class since there is no specific instance to use the members of. It can however call members of the outer class on an instance of the outer class, so you could for example do the following:
class A{
val a = "as".foo()
class B{
val b = A().run { "as".foo() }
}
fun String.foo(){}
}
Even though foo is an extension function, it's also a member of A because of where it's declared. Using a scope function that causes a class to be a receiver inside the scope is one way to call one of its member extension functions from another class.
EDIT: Here's an example of one reason you'd want to declare an extension inside a class.
class Sample(val id: Int) {
private val tag = "Sample#$id"
fun String.alsoLogged(): String{
Log.d(tag, this)
return this
}
}
You can use this extension to easily log Strings you're working with inside the class (or when it's the receiver of run or apply). It wouldn't make sense to declare outside the class because it uses the private tag property of that class.
It's because Kotlin compiles your code to
public final class A {
#NotNull
private final Unit a;
#NotNull
public final Unit getA() {
return this.a;
}
public final void foo(#NotNull String $this$foo) {
Intrinsics.checkNotNullParameter($this$foo, "$this$foo");
}
public A() {
this.foo("as");
this.a = Unit.INSTANCE;
}
public static final class B {
public B() {
// You can't access A's foo() method here.
}
}
}

(Interface, Class) Kotlin: Expecting member declaration

Class Aim: read review point and comment, ensure that point is within 0-5
class LimitedReview(val point:Int, val comment:String):Review {
if (point<0){
point=0
}
if (point>5){
point = 5
}
override fun stars(): Int =point
override fun info(): String =comment
}
interface Review{
fun stars():Int
fun info():String
}
Error:(2, 5) Kotlin: Expecting member declaration
Error:(2, 17) Kotlin: Conflicting overloads: public final fun (): Unit defined in LimitedReview, public final fun (): Unit defined in LimitedReview
Error:(2, 17) Kotlin: Function declaration must have a name
may i know how to change my code?
which topic should i learn to avoid the same error again?
Thanks!
The property you have in the primary constructor of the class will assign the value that you call the constructor with to the point property directly, when your class is created, and you can't modify it any more.
Basically, this code:
class LimitedReview(val point: Int)
Is the same as this:
class LimitedReview(point: Int) {
val point: Int = point // ctor param to property
}
If you want to perform logic before assigning the value to the property, you have to move the property outside the constructor, and initialize it manually.
This can be done in an initializer block, if you have complex logic for it:
class LimitedReview(point: Int) {
val point: Int
init {
if (point < 0) {
this.point = 0
} else if (point > 5) {
this.point = 5
} else {
this.point = point
}
}
}
Or if you can fit it into a single expression (coerceIn comes in handy here), then inline with the property declaration:
class LimitedReview(point: Int) {
val point: Int = point.coerceIn(0..5)
}

Kotlin data class with different backing field type

I have a simple class used for JSON serialization. For this purpose, the external interface uses Strings, but the internal representation is different.
public class TheClass {
private final ComplexInfo info;
public TheClass(String info) {
this.info = new ComplexInfo(info);
}
public String getInfo() {
return this.info.getAsString();
}
// ...more stuff which uses the ComplexInfo...
}
I have this working in Kotlin (not sure if there's a better way). But the non-val/var constructor prevents me from using data.
/*data*/ class TheClass(info: String) {
private val _info = ComplexInfo(info)
val info: String
get() = _info.getAsString()
// ...more stuff which uses the ComplexInfo...
}
How do I get this working as a data class?
You can use a combination of a private ComplexInfo property declared in the primary constructor and a secondary constructor that accepts a String.
Optionally, make the primary constructor private.
Example:
data class TheClass private constructor(private val complexInfo: ComplexInfo) {
constructor(infoString: String) : this(ComplexInfo(infoString))
val info: String get() = complexInfo.getAsString()
}
Note that it's the complexInfo property that is used in the data class generated members implementations.