在Android开发中密封类的实例
Practical example of sealed classes in Android Development
我是 Kotlin 的新手。我正在学习 sealed classes
,但我不明白如何在 Android 开发中使用它。你可以给我一个例子吗?
当您想定义子类的封闭列表时,它很有用。
您可以使用 possibility for data classes to extend sealed classes 。示例:
fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
// the `else` clause is not required because we've covered all the cases
}
声明:
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
Kotlin 文档说:
Sealed classes are used for representing restricted class hierarchies, when a value can have one of the types from a limited set, but cannot have any other type.
举个简单的例子。你有一个密封的摘要 class 代表一个布尔表达式:
sealed class BooleanExpression {
abstract fun evalate(): Boolean
}
现在让我们定义一个 class 来扩展这个密封的 class:
class OrBooleanExpression(val elem1: Boolean, val elem2: Boolean) : BooleanExpression() {
override fun evalate() = elem1 or elem2
}
现在让我们假设我们想要一个只打印布尔表达式成员的方法。对于我们的 or 布尔表达式,我们将有以下内容:
Elem1 true / Elem2 false
我们可以像下面这样实现我们的方法:
fun printMembers(expr: BooleanExpression) = when (expr) {
is OrBooleanExpression -> print("Elem1 ${expr.elem1} / Elem2 ${expr.elem2}")
}
到目前为止,我们的编译器很满意。没有错误。事实上,在我们的 when
中,我们已经考虑了密封 class.
的所有子class
现在让我们添加另一个布尔表达式:
class NotBooleanExpression(val elem1: Boolean) : BooleanExpression() {
override fun evalate(): Boolean = !elem1
}
现在编译returns一个错误:
'when' expression must be exhaustive, add necessary 'is NotBooleanExpression' branch or 'else' branch instead
现在我们有两种可能性来解决这个问题。首先是为新操作添加一个子句:
fun printMembers(expr: BooleanExpression) = when (expr) {
is OrBooleanExpression -> print("Elem1 ${expr.elem1} / Elem2 ${expr.elem2}")
is NotBooleanExpression -> print("Elem1 ${expr.elem1}")
}
或者我们可以添加一个 else
子句:
fun printMembers(expr: BooleanExpression) = when (expr) {
is OrBooleanExpression -> print("Elem1 ${expr.elem1} / Elem2 ${expr.elem2}")
else -> print("Unknown elements")
}
在这两种情况下,编译都有效,因为我们已经处理了密封 class.
的所有子classes
如果现在我们考虑一种当前未密封的语言 class,例如 Java。我们将无法在编译时执行此操作。因此,您需要使用设计模式 Visitor.
来实现以下内容
interface BooleanExpression {
abstract Boolean evaluate();
abstract <T> T accept(Visitor<T> visitor);
}
class NotBooleanExpression implements BooleanExpression {
private String elem1;
public NotBooleanExpression(String elem1) {
this.elem1 = elem1;
}
public Boolean getElem1() {
return elem1;
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
class OrBooleanExpression implements BooleanExpression {
private String elem1;
private String elem2;
public NotBooleanExpression(String elem1, String elem2) {
this.elem1 = elem1;
this.elem2 = elem2;
}
public Boolean getElem1() {
return elem1;
}
public Boolean getElem2() {
return elem2;
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
class Visitor<T> {
T visit(NotBooleanExpression expr);
T visit(OrBooleanExpression expr);
}
class Test {
public void printMembers(expr: BooleanExpression) {
expr.accept(new Visitor<Void>() {
@Override
public Void visit(NotBooleanExpression expr) {
System.out.println("Elem1 " + expr.getElem1());
return null;
}
@Override
public Void visit(OrBooleanExpression expr) {
System.out.println("Elem1 " + expr.getElem1() + " / Elem2" + expr.getElem2());
return null;
}
};
}
}
我是 Kotlin 的新手。我正在学习 sealed classes
,但我不明白如何在 Android 开发中使用它。你可以给我一个例子吗?
当您想定义子类的封闭列表时,它很有用。
您可以使用 possibility for data classes to extend sealed classes 。示例:
fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
// the `else` clause is not required because we've covered all the cases
}
声明:
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
Kotlin 文档说:
Sealed classes are used for representing restricted class hierarchies, when a value can have one of the types from a limited set, but cannot have any other type.
举个简单的例子。你有一个密封的摘要 class 代表一个布尔表达式:
sealed class BooleanExpression {
abstract fun evalate(): Boolean
}
现在让我们定义一个 class 来扩展这个密封的 class:
class OrBooleanExpression(val elem1: Boolean, val elem2: Boolean) : BooleanExpression() {
override fun evalate() = elem1 or elem2
}
现在让我们假设我们想要一个只打印布尔表达式成员的方法。对于我们的 or 布尔表达式,我们将有以下内容:
Elem1 true / Elem2 false
我们可以像下面这样实现我们的方法:
fun printMembers(expr: BooleanExpression) = when (expr) {
is OrBooleanExpression -> print("Elem1 ${expr.elem1} / Elem2 ${expr.elem2}")
}
到目前为止,我们的编译器很满意。没有错误。事实上,在我们的 when
中,我们已经考虑了密封 class.
现在让我们添加另一个布尔表达式:
class NotBooleanExpression(val elem1: Boolean) : BooleanExpression() {
override fun evalate(): Boolean = !elem1
}
现在编译returns一个错误:
'when' expression must be exhaustive, add necessary 'is NotBooleanExpression' branch or 'else' branch instead
现在我们有两种可能性来解决这个问题。首先是为新操作添加一个子句:
fun printMembers(expr: BooleanExpression) = when (expr) {
is OrBooleanExpression -> print("Elem1 ${expr.elem1} / Elem2 ${expr.elem2}")
is NotBooleanExpression -> print("Elem1 ${expr.elem1}")
}
或者我们可以添加一个 else
子句:
fun printMembers(expr: BooleanExpression) = when (expr) {
is OrBooleanExpression -> print("Elem1 ${expr.elem1} / Elem2 ${expr.elem2}")
else -> print("Unknown elements")
}
在这两种情况下,编译都有效,因为我们已经处理了密封 class.
的所有子classes如果现在我们考虑一种当前未密封的语言 class,例如 Java。我们将无法在编译时执行此操作。因此,您需要使用设计模式 Visitor.
来实现以下内容interface BooleanExpression {
abstract Boolean evaluate();
abstract <T> T accept(Visitor<T> visitor);
}
class NotBooleanExpression implements BooleanExpression {
private String elem1;
public NotBooleanExpression(String elem1) {
this.elem1 = elem1;
}
public Boolean getElem1() {
return elem1;
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
class OrBooleanExpression implements BooleanExpression {
private String elem1;
private String elem2;
public NotBooleanExpression(String elem1, String elem2) {
this.elem1 = elem1;
this.elem2 = elem2;
}
public Boolean getElem1() {
return elem1;
}
public Boolean getElem2() {
return elem2;
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
class Visitor<T> {
T visit(NotBooleanExpression expr);
T visit(OrBooleanExpression expr);
}
class Test {
public void printMembers(expr: BooleanExpression) {
expr.accept(new Visitor<Void>() {
@Override
public Void visit(NotBooleanExpression expr) {
System.out.println("Elem1 " + expr.getElem1());
return null;
}
@Override
public Void visit(OrBooleanExpression expr) {
System.out.println("Elem1 " + expr.getElem1() + " / Elem2" + expr.getElem2());
return null;
}
};
}
}