Sealed class: KAD 28, kotlinkad
By Antonio Leiva
Time: Jun 27,201 7
Link: https://antonioleiva.com/sealed-classes-kotlin/
The Kotlin encapsulation class is a new concept not available in Java, and opens up another world of possibilities.
Sealing class allows youExpresses the constraint hierarchy. An object can only be one of the given types..
That is to say, we have a class with a specific number of subclasses. Finally, we can conclude that the concept of enumeration is very similar. The difference is that in enumeration, each type has only one object, while in the sealed class, the same class can have several objects.
This differenceObjects of the seal class can be kept in the state.. This brings us some advantages (we will see it later) and opens the door to functional concepts.
How to Use the seal class
In fact, it is very easy to implement the sealing class. Let's look at a group of examples that can be applied to integer operations.
The implementation is as follows:
1 sealed class Operation {2 class Add(val value: Int) : Operation()3 class Substract(val value: Int) : Operation()4 class Multiply(val value: Int) : Operation()5 class Divide(val value: Int) : Operation()6 }
We createOperation
It contains four operations: addition, subtraction, multiplication, and division.
This is, nowwhen
The expression requires that we provide branches for all possible types:
1 fun execute(x: Int, op: Operation) = when (op) {2 is Operation.Add -> x + op.value3 is Operation.Substract -> x - op.value4 is Operation.Multiply -> x * op.value5 is Operation.Divide -> x / op.value6 }
If you leave any subclass,WhenWill complain that it will not compile. If you implement them, you do not need the else statement. Generally, we do not recommend this because we are sure we do the right thing for everyone.
It will fail during compilation and will not run. If you decide to add a new operation, this will also be very good. Add one operation, increment, and decrease:
1 sealed class Operation {2 ...3 object Increment : Operation()4 object Decrement : Operation()5 }
Now, you will see the compiler warning you that there is a problem. You only need to add branches for these new operations:
1 fun execute(x: Int, op: Operation) = when (op) {2 ...3 Operation.Increment -> x + 14 Operation.Decrement -> x - 15 }
You may have noticed that I have done something different. I use objects instead of classes. This is because if a subclass is not in the maintained State, it can only be an object. All instances you create for this class will be identical, and they cannot be in different States.
Inwhen
In the expression, you can get rid of the situationsis
. Here, because there is only one instance, you can only compare objects, you do not need to check the object type. You can retainis
It can also work.
If you think about it carefully, all subclasses are the same as the sealing class of the object and enumeration.
Move side effects to Single Point
The side effects of function programming are a very common concept. Function programming relies heavily onFor a given function, the same result will be returned for the same Parameter.
Any modification may undermine this assumption. However, any program must change its status and communicate with input/output elements. Therefore, it is important to discover these operations in our code and easily isolate them to specific places.
For example, any operation implemented on the Android view is considered as a side effect because the view State is modified and the function is unknown.
We can create a sealed class so that we can operate on The View. Based on this concept, the previous example is as follows:
1 sealed class UiOp { 2 object Show: UiOp() 3 object Hide: UiOp() 4 class TranslateX(val px: Float): UiOp() 5 class TranslateY(val px: Float): UiOp() 6 } 7 8 fun execute(view: View, op: UiOp) = when (op) { 9 UiOp.Show -> view.visibility = View.VISIBLE10 UiOp.Hide -> view.visibility = View.GONE11 is UiOp.TranslateX -> view.translationX = op.px12 is UiOp.TranslateY -> view.translationY = op.px13 }
Remember: Because we don't need different instances, stateless operations can be objects.
Now, you can createUi
Object, which aggregates all interface operations to be performed on the view until we need it.
We will describe what we want to do, and then we can create a component to execute them:
1 class Ui(val uiOps: List = emptyList()) {2 operator fun plus(uiOp: UiOp) = Ui(uiOps + uiOp)3 }
Ui
Class storage operation list, and specify an accumulation and operator, which will help make all content clearer and easier to read. Now we can specify the list of operations to be executed:
1 val ui = Ui() +2 UiOp.Show +3 UiOp.TranslateX(20f) +4 UiOp.TranslateY(40f) +5 UiOp.Hide6 7 run(view, ui)
Then run it. Here I just userun
Function, but if needed, this can be a complete class.
1 fun run(view: View, ui: Ui) {2 ui.uiOps.forEach { execute(view, it) }3 }
Imagine that everything you do now runs in order, but this may be complicated.
Thisrun
A function can be passed to another function or class, andThe running Modes of those operations will be completely interchangeable.. Remember that you can pass functions as parameters.
Conclusion
The concept of the sealing class is very simple, but if you have not used functional programming before, you need some foundation to use the new concept.
I must say that due to my knowledge limitations in functional programming, I have not used the sealing class to the maximum extent.
If you are keen on this as I do, I suggest you view previous articles, where you can learn more about Kotlin, you can also learn how to use Kotlin to create a complete Android Application from scratch.
Val ui = Ui () +
UiOp. Show +
UiOp. TranslateX (20f) +
UiOp. TranslateY (40f) +
UiOp. Hide
Run (view, ui)