ByteCode, dedicated to share the latest technology original articles, involving Kotlin, Jetpack, translation, system source code, LeetCode/point Offer/multithreading/domestic and foreign large factory algorithm problems and so on a series of articles.

In my previous article, I covered the nature of Sealed Classes and why Google and many other open source projects are using it extensively. If you’re not familiar with Sealed Classes, check out Kotlin Sealed. Here’s why Google is using it:

  • Sealed Classes
  • What are the limitations of enumerations and abstract classes?
  • Why can enumerations be singletons? What are the advantages of enumerations as singletons?
  • When are enumerations and Sealed Classes used?
  • What exactly are Sealed Classes?
  • Why Sealed Classes are used to represent a restricted class hierarchy?
  • Sealed Classes is an extension of an enumeration class.
  • A subclass of Sealed Classes can represent instances of different states. How can it be used in a project?
  • How did Kotlin do this?

In this article, we will discuss the advantages and disadvantages of Sealed Classes and Tagged Classes in terms of class hierarchies. Before we get started, let’s talk about what Tagged Classes are and what their drawbacks are.

What is Tagged Classes

Classes that include a tag field or feature in a class that indicates an operation and make it easy to switch between them are called Tagged Classes. Effective Java also points out that Tagged Classes have many problems. This article uses an example from Effective Java Item 23 to analyze Tagged Classes, rewritten by Kotlin.

Class Figure(val shape: shape, val radius: Double = 0.0, val length: Double = 0.0, val width: Double = 0.0) {// RECTANGLE class Shape {RECTANGLE, CIRCLE} Double = when (shape) { Shape.RECTANGLE -> length * width Shape.CIRCLE -> Math.PI * (radius * radius) else -> throw AssertionError(shape) } companion object { fun createRectangle(radius: Double) { Figure( shape = Shape.RECTANGLE, radius = radius ) } fun createCircle(length: Double, width: Double = 0.0) {Figure(shape = shape.CIRCLE, length = length, width = width)}}}Copy the code

As you can see, the code contains a lot of template code, including the tag field, switch statements, enums, etc., in a class contains many different operations, if after adding new operation, have a need to add a new markup, such code in the project actual situation is very common, there are the following questions:

  • Added a lot of template code
  • Memory is a scarce resource, and when we create a circle, fields that are not related to it should also be retained, increasing the memory occupied by the current class
  • Reduced code readability, classes are mixed with operations such as enumerations, switch statements, etc., and design patterns such as factory mode are often used to ensure that objects are created correctly
  • If you add new graphics, you have to modify the existing code structure
  • .

Is there a good alternative that can solve all of the above problems and still add new graphics without modifying the original code structure, which requires a class hierarchy?

Class hierarchy

In both Java and Kotlin, we use class hierarchies instead of tag Classes. In Kotlin, we often use Sealed Classes to refer to a restricted class hierarchy. In the previous article, what is Kotlin Sealed? Sealed Classes has been analyzed in detail in Sealed Classes. Let’s take a look at optimizing the code above using Sealed Classes.

sealed class Figure {
    abstract fun area(): Double

    class Rectangle(val length: Double, val width: Double) : Figure() {
        override fun area(): Double = length * width
    }

    class Circle(val radius: Double) : Figure() {
        override fun area(): Double = Math.PI * (radius * radius)
    }
}
Copy the code

As you can see, the code is much cleaner, no template code is included, and the responsibilities between classes are clear, which increases the flexibility of the code and perfectly addresses all of the above shortcomings. Each class does not contain extraneous fields, and adding new parameters to the class does not affect other classes.

If we need to add a new shape, we can just add a new class without breaking the code structure, as we did here by adding a sphere.

Class Ball(val radius: Double) : Figure() {override fun area(): Double = 4.0 * math.pi * math.pow (radius, 2.0)} class Ball(val radius: Double) : Figure() {override fun area(): Double = 4.0 * math.pi * math.pow (radius, 2.0)}Copy the code

Not only that, Sealed Classes is much easier to use with the WHEN expression. All branches under the WHEN statement can be automatically generated using the Mac/Win/Linux: Alt + Enter shortcut, as shown below.

fun Figure.Valida() {
    when (this) {
        is Figure.Ball -> {
            println("I am Ball")
            area()
        }
        is Figure.Circle -> {
            println("I am Circle")
            area()
        }
        is Figure.Rectangle -> {
            println("I am Rectangle")
            area()
        }
    }
}
Copy the code

In Effective Java, it is also shown that Tagged classes are rarely suitable. However, in order to develop a function quickly, the impact of Tagged classes is often ignored. However, when we make optimization, Kotlin suggests Sealed classes instead of Tagged classes.

Refer to the article

  • Effective Java Item 23: Prefer class hierarchies to tagged classes
  • Effective Kotlin Item 40: Prefer class hierarchies to tagged classes


This is the end of the article, if it is helpful to give me a thumbs up is the biggest encouragement

More code, more articles

Welcome to the public account: ByteCode, continue to share the latest technology



Finally, I recommend the projects and websites I have been updating and maintaining:

  • Androidx-jetpack-practice androidX-Jetpack-practice androidX-Jetpack-Practice androidX-Jetpack-Practice AndroidX-Jetpack-Practice

  • LeetCode/multiple thread solution, language Java and Kotlin, including a variety of solutions, problem solving ideas, time complexity, spatial complexity analysis

    • Job interview with major companies at home and abroad
    • LeetCode: Read online
  • Android10 Source code Analysis series of articles, understand the system Source code, not only help to analyze the problem, in the interview process, is also very helpful to us, the warehouse continues to update, welcome to check android10-source-Analysis

  • Collate and translate a series of selected foreign Technical articles, each Article will have a translator’s thinking part, a more in-depth interpretation of the original text, the warehouse continues to update, welcome to visit the Technical-Article-Translation

  • “Designed for Internet people, navigation of domestic and foreign famous stations” includes news, sports, life, entertainment, design, product, operation, front-end development, Android development and so on. Welcome to check the navigation website designed for Internet people

Article history

  • What did LeetCode learn from going from 0 to 200
  • Android 12 behavior changes that affect applications
  • AndroidStudio
  • Kotlin’s Technique and Principle Analysis that few people know (1)
  • Kotlin’s Technique and Principle Analysis that few people know (II)
  • AndroidX App Startup practice and principle analysis of Jetpack’s latest member
  • Jetpack member Paging3 retrieves network page data and updates it to the database
  • New member of Jetpack Hilt and Dagger are very different
  • All aspects of Hilt and Koin performance were analyzed
  • PokemonGo Jetpack + MVVM minimalism
  • What is Kotlin Sealed? Why does Google use them all
  • Kotlin StateFlow search features practice DB + NetWork
  • [Google] Bye SharedPreferences embrace Jetpack DataStore
  • The end of the Kotlin plugin and the rise of ViewBinding
  • Surprisingly simple, DataBinding and ViewBinding