0

the code below compiles while it is impossible to go through conditions Color.Dark and Color.Light as these two classes are abstract.

Did I miss something ?

sealed class Color () {
  sealed class Dark () {
    class DarkRed : Color()
    class DarkBlue : Color()
    }   
  sealed class Light {
    class LightRed : Color()
    class LightBlue : Color()
    }
}   

fun eval(c: Color) =
        when (c) {
        is Color.Dark -> println("Dark")
            is Color.Dark.DarkRed -> println("Dark Red")
            is Color.Dark.DarkBlue -> println("Dark Blue")

        is Color.Light -> println("Light")
            is Color.Light.LightRed -> println("Light Red")
            is Color.Light.LightBlue -> println("Light Blue")
}

fun main(args: Array<String>) {
    val dr = Color.Dark.DarkRed()
    eval(dr)
}
Emile Achadde
  • 1,715
  • 3
  • 10
  • 22
  • Ask your IDE to reformat the whole file for you. Your indentation is tricking you. There is no hierarchy between the clauses of your when statement. There is no "going through Color.Dark". – JB Nizet Jan 19 '20 at 16:51
  • May I ask the question differently : why this code compiles ? The two left indented conditions are never satisfied. – Emile Achadde Jan 19 '20 at 17:08
  • 1
    `val i = 0; if (i == 1) { ... }` compiles too, even though `i == 1` will never be satisfied.The compiler doesn't care if a condiin will never be satisfied at runtime. It cares if your code is syntaxically correct. – JB Nizet Jan 19 '20 at 22:11
  • 1
    @JBNizet If you change `Color.Dark` to `String` it _doesn't_ compile with the error `Incompatible types: String and Color`. And `Color.Dark` is just as incompatible with `Color` as `String` is. I think this is a bug. – Alexey Romanov Jan 20 '20 at 07:51
  • @AlexeyRomanov But if you replace it with `Number`, it compiles. My guess is that it doesn't compile with String because String is final, and there is thus no way a Color can extend String. But I agree that there is also no way a Color can extend Number. – JB Nizet Jan 20 '20 at 08:29
  • @JBNizet I thought the difference is that `Number` is an interface, so there can be something like `object : Color, Number ...`, but it's actually an abstract class. So I think they should be incompatible as well. – Alexey Romanov Jan 20 '20 at 09:38
  • @JBNizet Plus from a quick experiment in Java they seem to be incompatible, so it isn't even about preserving compilability when porting... – Alexey Romanov Jan 20 '20 at 09:43

1 Answers1

2

Two left indented conditions are never satisfied because Color.Dark and Color.Lightdo not inherit Color, and not because they are abstract. It means that 2 out of 6 is branches are useless, you can safely delete them. But other 4 branches (is Color.Dark.DarkRed, etc.) go through all Color subclasses, and Color is a sealed class, so when can be used without else branch.

ardenit
  • 3,610
  • 8
  • 16