Elye
Elye

Reputation: 60321

Can a field be cast to non null version of itself?

I have a data class

data class MyModel(private val _data: MyData? = null)

And I want to ensure my data is only accessible when it is not null, else throw. I use the below which is good.

    fun getData(): MyData {
        return checkNotNull(_data) { "data shouldn't be null" }
    }

However, if I follow the guide as per Override getter for Kotlin data class, the below complaints I need to return MyData? instead of MyData

val data = _data
    get(): MyData {
        return checkNotNull(field) { "data shouldn't be null" }
    }

Is it true that field can't be cast to the Non-null version of it when return?

Upvotes: 3

Views: 674

Answers (3)

Vince
Vince

Reputation: 15146

If your goal is to declare a getter for a Any? property that returns a Any, it's not possible. You'll get the following error:

Getter return type must be equal to the type of the property

So attempting to do something like

val test : String?
    get() : String = "hi"

Wouldn't work.


However, you could hide the nullable property and expose a non-nullable property which references the nullable value via casting:

private val test : String? = "hi"
val testNotNull : String = test as String

If test referenced null, an exception will be thrown.

For example:

fun main(args: Array<String>) = print(Demo().testNotNull)

class Demo(private var test: String? = "hi") {
    val testNotNull : String
.       get() = test as String
}

You can test this snippit out at try.kotlin.org

Although this is not safe. You should rethink your design. If you're not interoping with Java, you shouldn't punish yourself with nullable types.

Upvotes: 2

Martin Marconcini
Martin Marconcini

Reputation: 27246

I don’t think you can. What you did with the fun getData() is a valid approach IMO. Or you could just not use a data class and create a normal class, obviously.

What I think it may work is with something like this:

typealias notNullType = MyData

data class Test(private val _value: MyData? = null) {
    val v: notNullType = _value as notNullType
    get() { return field }
}

This would totally allow you to do:

fun play() {
    val t = Test(null)
    print(t.v) //see what I did? :-)
}

THAT BEING SAID… I don’t think “hiding” the ? optional is necessarily a good idea.

Upvotes: 1

ganjeii
ganjeii

Reputation: 1178

It doesn't necessarily mean that the MyData class is null if you cast it like MyData?

The '?' Just allows the object to be null in the instance that it actually becomes null to avoid an exception at runtime.

You can make your class nullable and it can still contain your data.

Upvotes: 0

Related Questions