Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
334 views
in Technique[技术] by (71.8m points)

kotlin - Unnecessary/broken check for abstract intermediary subclass of sealed class required in exhaustive when

I have a sealed class hierarchy like so:

sealed class Base

class A : Base()

abstract class B : Base()

class C : Base()
class D : Base()

Then I want to have an exhaustive when:

fun main() {
    val c: Base = C()
    
    when (c) {
        is A -> println("A")
        is C -> println("C")
        is D -> println("D")
    }.let {}
}

But this is not allowed because

'when' expression must be exhaustive, add necessary 'is B' branch or 'else' branch instead

But that's not true! I've covered all possibilities. There is no value that isn't matched by my when.

Furthermore, if I do add a is C clause:

when (c) {
    is A -> println("A")
    is B -> println("B")
    is C -> println("C")
    is D -> println("D")
}.let {}

It isn't actually called. C is printed.

This is actually a problem in the other direction, too. Say I want the same logic to handle all subclasses of B: C and D:

when (c) {
    is A -> println("A")
    is B -> println("some subclass of B")
}.let {}

That's also not allowed, even though it is exhaustive. What's going on here? Is this a bug in Kotlin? Am I missing something?

question from:https://stackoverflow.com/questions/65911484/unnecessary-broken-check-for-abstract-intermediary-subclass-of-sealed-class-requ

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Assuming you meant for C and D to be subclasses of B rather than Base, then this behavior is expected. The ability of the compiler to recognize an exhaustive when statement only extends to the direct children of the sealed class. C and D are not part of the sealed class contract. This works with your existing class setup if C and D extend B:

when (c) {
    is A -> println("A")
    is B -> println("B")
}.let {}

And if you make B a sealed class, just like A, your original code works and the compiler can recognize that it's exhaustive without including B in the when statement.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...