简体   繁体   中英

Why is there a object class defined within sealed class when I use Kotlin?

The Code A is from the official sample project .

Result<out R> is a sealed class, I'm very strange why Loading is defined as object class.

I think the Code B is more reasonable, is it right?

Code A

sealed class Result<out R> {
   data class Success<out T>(val data: T) : Result<T>()
   data class Error(val exception: Exception) : Result<Nothing>()
   object Loading : Result<Nothing>()

   override fun toString(): String {
      return when (this) {
         is Success<*> -> "Success[data=$data]"
         is Error -> "Error[exception=$exception]"
         Loading -> "Loading"
      }
   }
}

Code B

sealed class Result<out R> {
   data class Success<out T>(val data: T) : Result<T>()
   data class Error(val exception: Exception) : Result<Nothing>()
   data class Loading : Result<Nothing>()

   override fun toString(): String {
      return when (this) {
         is Success<*> -> "Success[data=$data]"
         is Error -> "Error[exception=$exception]"
         is Loading -> "Loading"
      }
   }
}

Added Content:

To Tenfour04 and a_local_nobody: Thanks!

The Android Studio can compile and run after I add is before Loading -> "Loading" in Code C.

1: What are differents between Code A and Code C?

2: And more, In my mind, all types whithin sealed class should be the same, maybe they are all data class, or they are all object. But Code A mix data class and object, and it's Ok, does it mean that I add even Interface whithin sealed class?

Code C

sealed class Result<out R> {
   data class Success<out T>(val data: T) : Result<T>()
   data class Error(val exception: Exception) : Result<Nothing>()
   object Loading : Result<Nothing>()

   override fun toString(): String {
      return when (this) {
         is Success<*> -> "Success[data=$data]"
         is Error -> "Error[exception=$exception]"
         is Loading -> "Loading"     // I add "is"
      }
   }
}

There's no reason not to use an object for a class that doesn't have any properties (holds no state). object means you don't have to create multiple instances of it and you never have to worry about which instance you're looking at, so it's simpler. You don't have to call a constructor on it to get an instance, and there will never be more than one instance of it taking up memory.

Note that your is Loading check in Code B will still work if Loading is an object . object s are more versatile because == and is checks are both valid and effectively mean the same thing.

By the way (as mentioned before by @a_local_nobody), you cannot create a data class with no properties, although you could create a regular class.

that won't work, because:

data class Loading : Result<Nothing>() <-- this isn't valid for a data class

Data classes must have at least one primary constructor parameter, presumably the author used an object there to avoid having to make use of a constructor value, compared to the others:

 data class Success<out T>(val data: T) : Result<T>() <-- (val data: T)
 data class Error(val exception: Exception) : Result<Nothing>() <-- (val exception: Exception)

which clearly require values

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM