Kotlin seal (Sealed) class: Super enumeration (KAD 28)

Original link: http://www.cnblogs.com/figozhg/p/7107053.html

Author: Antonio Leiva

Time: Jun 27, 2017

Original link: https://antonioleiva.com/sealed-classes-kotlin/

 

 

Kotlin wrapper classes are Java new concept is not in, and to that end a new world opened up the possibility of another piece.

 

Sealed class allows you to express constraints hierarchy, where the object is only one of a given type .

 

 

That is, we have a certain number of classes have subclasses. Finally, we get to the conclusion that the concept is very similar to enumerate. The difference is that, in the enumeration, each of us is only one type of objects; and in a sealed class, the same class can have several objects.

 

 

This difference allows the object class can be kept sealed state . This gives us some advantages (see later), it opened its doors as a function of the concept.

 

 

How to use sealed class

 

 

 

In fact , very simple sealing type. Let's look at a set of examples can be applied to integer operations.

 

 

Achieved 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 create a named Operationsealed class, comprising four operations: addition, subtraction, multiplication and division.

 

 

This benefit is now whenan expression requires us to provide branch for all possible types:

 

1 fun execute(x: Int, op: Operation) = when (op) {
2     is Operation.Add -> x + op.value
3     is Operation.Substract -> x - op.value
4     is Operation.Multiply -> x * op.value
5     is Operation.Divide -> x / op.value
6 }

 

 

If you leave any of a subclass, the when will complain that it does not compile . If you achieve them, you do not need else statement. In general, since we are convinced that we all do the right thing, this is not recommended.

 

 

Because it will fail at compile time, and will not run, if you decide to add a new operation, this is also very good. Now add a couple of operations, increment and decrement:

 

1 sealed class Operation {
2     ...
3     object Increment : Operation()
4     object Decrement : Operation()
5 }

 

 

Now, you will see a compiler warning you that there is a problem. Just add a new branch for these operations:

 

1 fun execute(x: Int, op: Operation) = when (op) {
2     ...
3     Operation.Increment -> x + 1
4     Operation.Decrement -> x - 1
5 }

 

 

You may have noticed that I have done things differently. I use an object instead of a class. This is because if a subclass does not hold, it can only be an object. You created for all instances of the class will be exactly the same, they can not have different states.

 

Then, in whenan expression, you can get rid of those cases is. Here, because only one instance, you can compare objects, you need to check the type of object. If those, you can keep is, it can work.

 

 

If you think about it, the same sealed class and enumerates all subclasses are objects.

 

 

The move to a single point on side effects

 

 

 

函数编程的副作用是一个非常通用概念。函数编程在很大程度上依赖于给定的功能,相同的参数将返回相同的结果

 

 

任何修改状态都可能会破坏这一假设。但是任何程序都需要更改状态,与输入/输出元素进行通讯等。因此,重要的是如何在我们的代码中发现这些操作,并很容易隔离到特定地方。

 

例如,在Android视图上实现的任何操作都被视为副作用,因为视图的状态修改,而函数不知道。

 

我们可以创建一个密封类,使我们能够对视图进行操作。基于这个概念,以前的例子:

 

 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.VISIBLE
10     UiOp.Hide -> view.visibility = View.GONE
11     is UiOp.TranslateX -> view.translationX = op.px
12     is UiOp.TranslateY -> view.translationY = op.px
13 }

 

 

记住:因为我们不需要不同的实例,没有状态的操作就可以是对象。

 

 

现在,你可以创建一个Ui对象,汇集要在视图上做的所有接口操作,直到我们需要时,才执行它。

 

 

我们将描述我们想要做什么,然后我们可以创建一个执行它们的组件:

 

1 class Ui(val uiOps: List = emptyList()) {
2     operator fun plus(uiOp: UiOp) = Ui(uiOps + uiOp)
3 }

 

 

Ui类存储操作列表,并指定一个累加和运算符,这将有助于使所有内容更清晰,更易于阅读。现在我们可以指定要执行的操作列表:

 

1 val ui = Ui() +
2         UiOp.Show +
3         UiOp.TranslateX(20f) +
4         UiOp.TranslateY(40f) +
5         UiOp.Hide
6 
7 run(view, ui)

 

 

 

然后运行它。这里我只是使用一个run函数,但如果需要,这可以是一个完整的类。

1 fun run(view: View, ui: Ui) {
2     ui.uiOps.forEach { execute(view, it) }
3 }

 

 

Imagine that, now all you do is run sequentially, but this can be complicated.

 

 

This runfunction can be passed to another function or class, and the operation mode of those operations will be fully interchangeable . Remember that you can be a function passed as a parameter .

 

 

in conclusion

 

 

Sealed class concept is very simple, but if you have not previously use functional programming, you need some basic use of new concepts.

 

 

I must say, because I am limited to knowledge of functional programming, I have yet to maximize the use of sealed classes.

 

 

If you're like me enthusiastic about this, I suggest you look at the previous articles, in which you can understand more about Kotlin of information , or in this book to learn how to use Kotlin from scratch to create a complete Android application .

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Ui Ui = val () +

        UiOp.Show +

        UiOp.TranslateX(20f) +

        UiOp.TranslateY(40f) +

        UiOp.Hide

 

run(view, ui)

Reproduced in: https: //www.cnblogs.com/figozhg/p/7107053.html

Guess you like

Origin blog.csdn.net/weixin_30919429/article/details/94789291