kotlin 例子_Kotlin一无所获的简单现实世界例子

kotlin 例子

Hi there! I want to share a pretty practical use of Kotlin’s Nothing type designation. If you are having trouble figuring out where Nothing is useful I hope the following example is a new way to see it in action in a tangible way.

嗨,您好! 我想分享Kotlin的Nothing类型名称的实用用法。 如果您在找出“无用的地方Nothing遇到麻烦,我希望以下示例是一种切实可行的新方法。

介绍我们的例子 (Introducing Our Example)

Our simple example will showcase the common use-case of parsing HTTP request parameters. Some parameters will be optional (nullable or missing), some parameters must be present (non-null), some must be present with content to parse (not blank), some must be present and alpha-numeric (like hex values), and so on. We want to enforce these restrictions as early as possible.

我们的简单示例将展示解析HTTP请求参数的常见用例。 一些参数将是可选的(可为空或缺失),一些参数必须存在(非空),一些参数必须与要解析的内容一起存在(非空白),某些参数必须存在并且为字母数字(如十六进制值),以及以此类推。 我们希望尽早执行这些限制。

Here is a basic version:

这是基本版本:

// types added for clarity
// getParameter is defined as:
// fun getParameter(name:String):String?
fun handle(): Unit
{
val optional:String? = getParameter(QP_OPTIONAL) val present:String = getParameter(QP_PRESENT)
?: return Logger.log("$QP_PRESENT was not provided.")
val content:String = getParameter(QP_CONTENT)
?: return Logger.log("$QP_CONTENT was not provided.")
if (content.isBlank())
{
return Logger.log("$QP_CONTENT was provided but empty.")
}
val someHash:String = getParameter(QP_HASH)
?: return Logger.log("$QP_HASH was not provided.")
if (someHash.isBlank() || !isAlphaNumeric(someHash))
{
return
Logger.log("$QP_HASH was provided but is not alpha-numeric.")
}
...
}

We’ve all been here, this can get quite lengthy and verbose. Let’s modify our getParameter function so that it can validate our parameters for us, so we don’t need to do it inline every time.

我们都来过这里,这可能会变得冗长冗长。 让我们修改getParameter函数,以便它可以为我们验证参数,因此我们不必每次都内联。

Image for post
Nothing is coming, I promise.
我保证什么都不会发生。

增加一些责任 (Add Some Accountability)

To make this happen, we will introduce a Result state to let us know if the parameter value meets our requirements or not.

为了实现这一点,我们将引入一个Result状态,让我们知道参数值是否满足我们的要求。

Here is a simple Result object that’s going to come in handy:

这是一个简单的Result对象,它将派上用场:

sealed class Result<out T>
{
data class Success<out T>(val value:T): Result<T>()
data class Failure<out T>(val message:String): Result<T>()
}

Also, we’ll create a Restriction class to define what rules the given parameter should conform to:

另外,我们将创建一个Restriction类来定义给定参数应遵循的规则:

sealed class Restriction
{
object NotNull: Restriction()
object NotBlank: Restriction()
object AlphaNumeric: Restriction()
}// note: nullable is not included here, since
// getParameter(name:String):String? is nullable to begin with...

Now we can define and implementfun getParameter(name:String, restriction:Restriction): Result<String>

现在我们可以定义和实现fun getParameter(name:String, restriction:Restriction): Result<String>

For this method hopefully it’s obvious that when the query parameter value passes the given restriction then it will be provided via the value field of a Success result; otherwise an error message is returned via the message field of a Failure result.

对于这种方法,希望当查询参数值超过给定的限制时,将通过Success结果的value字段将其提供;这很明显。 否则,将通过Failure结果的message字段返回错误消息。

Here is the basic version, updated to use our new Result and Restriction tools:

这是基本版本,已更新为使用我们新的ResultRestriction工具:

fun handle()
{
val optional = getParameter(QP_OPTIONAL) val present =
when(val result = getParameter(QP_PRESENT, Restriction.NotNull)
{
is Result.Success -> result.value
is Result.Failure -> return Logger.log(result.message)
}
val content =
when(result = getParameter(QP_CONTENT, Restriction.NotBlank)
{
is Result.Success -> result.value
is Result.Failure -> return Logger.log(result.message)
}
val someHash =
when(result = getParameter(QP_HASH, Restriction.AlphaNumeric)
{
is Result.Success -> result.value
is Result.Failure -> return Logger.log(result.message)
} // {checkpoint}
}

At {checkpoint} :

{checkpoint}

  • optional is of type String? and could be null and the compiler will enforce that in code following the declaration

    optionalString?类型String? 并且可以为null ,并且编译器将在声明之后的代码中强制执行该操作

  • present is of type String , cannot be null and that is enforced by the compiler following the declaration

    presentString类型的,不能为null并且由编译器在声明之后强制实施

  • content is of type String , cannot be null (enforced by the compiler); additionally getParameter can guarantee that content is not blank following the declaration

    contentString类型,不能为null (由编译器强制执行); 另外, getParameter可以保证声明后content不是空白

  • someHash is of type String , cannot be null (enforced by the compiler); additionally getParameter can guarantee that someHash is only alpha-numeric following the declaration

    someHash的类型为String ,不能为null (由编译器强制执行); 另外, getParameter可以保证声明后的someHash仅是字母数字

This is cleaner than our original example (since we have moved parameter validation to it’s own place), but it’s still cumbersome with some new boiler-plate code we have introduced. We can do better!

这比原始示例要干净(因为我们已经将参数验证移到了它自己的位置),但是对于我们引入的一些新的样板代码来说,它仍然很麻烦。 我们可以做得更好!

Image for post
Here is where nothing matters.
这是没有关系的地方。

Let’s jump right into it. We can add functionality to Result to enforce our heuristics here and remove a lot of duplicated code. For simplicity, I’ll add a function to Result like this:

让我们直接跳进去。 我们可以在Result添加功能以在此处强制执行启发式操作,并删除大量重复的代码。 为了简单起见,我将为Result添加一个函数,如下所示:

inline infix fun <T> check(block:(Result.Failure<T>) -> Nothing):T {return when (this) {is Result.Success -> this.valueis Result.Failure -> block(this)
}
}

Did you notice the block function parameter that returns Nothing? What’s happening here?

您是否注意到返回Nothingblock函数参数? 这里发生了什么事?

First of all, when the result is a success, it’s just returning that non-null value and not using block at all.

首先,当结果成功时,它只是返回该非null值,而根本不使用block

But when the result is a failure, the block gets executed and returns… Nothing? What does that mean? Let’s look back at our example from above, using our new check(...) method.

但是,如果结果是失败,则该block将被执行并返回…… Nothing ? 那是什么意思? 让我们使用新的check(...)方法从上方回顾示例。

fun handle()
{
val optional = getParameter(QP_OPTIONAL) val present = getParameter(QP_PRESENT, Restriction.NotNull) check
{ result -> return Logger.log(result.message) }
val content = getParameter(QP_CONTENT, Restriction.NotBlank) check
{ return Logger.log(it.message) }
val someHash =
getParameter(QP_HASH, Restriction.AlphaNumeric) check
{ return Logger.log(it.message) } // {checkpoint}
}

Notice that each block contains a return statement (which returns out of the function handle , not block). This means that if block is invoked it executes without returning anything to its caller (for us the caller is inside of our check function). This is the Nothing scenario.

注意,每个block包含一个return语句(该语句从函数handle返回, 而不是 block )。 这意味着,如果调用块,则它执行时不会返回任何内容给调用者(对我们而言,调用者位于我们的check函数内部)。 这是Nothing

This would also be true if we chose to throw inside the block, instead of return —throwing interrupts the execution of the block, and exits its scope immediately. These are two common ways that the compiler will enforce blocks that are defined to return Nothing .

如果我们选择在块内throw而不是return ,也将是正确的— throw会中断块的执行并立即退出其范围。 这是编译器将强制执行定义为返回Nothing块的两种常用方法。

In our example, this lets us very cleanly populate our variables with restrictions we choose to impose, and to return cleanly when those conditions are not met. To hammer home that point, the {checkpoint} conditions still hold that at {checkpoint}:

在我们的示例中,这使我们可以很干净地用我们选择施加的限制来填充变量,并在不满足这些条件时干净地返回。 为了说明这一点, {checkpoint}条件仍然保持在{checkpoint}

  • optional is of type String? and could be null and the compiler will enforce that in code following the declaration

    optionalString?类型String? 并且可以为null ,并且编译器将在声明之后的代码中强制执行该操作

  • present is of type String , cannot be null and is enforced by the compiler following the declaration

    presentString类型的,不能为null ,由声明后的编译器强制执行

  • content is of type String , cannot be null (enforced by the compiler); additionally getParameter can guarantee that content is not blank following the declaration

    contentString类型,不能为null (由编译器强制执行); 另外, getParameter可以保证声明后content不是空白

  • someHash is of type String , cannot be null (enforced by the compiler); additionally getParameter can guarantee that someHash is only alpha-numeric following the declaration

    someHash的类型为String ,不能为null (由编译器强制执行); 另外, getParameter可以保证声明后的someHash仅是字母数字

Not only that, the compiler will force us to either return or throw in the failure block we provide to the check function. Once we reach {checkpoint} in our code, we can use our variables with all of our restrictions enforced.

不仅如此,编译器还将迫使我们returnthrow我们提供给check函数的故障块。 一旦在代码中达到{checkpoint} ,就可以使用变量并强制执行所有限制。

That’s it! Thanks for reading — hopefully you learned something new about Nothing. Please get in touch if you have more to add to the conversation, or if I’ve made any errors and I will do my best to correct or address any and all of them.

而已! 感谢您的阅读-希望您学到了有关Nothing的新知识。 如果您还有更多要添加到对话中的内容,或者我犯了任何错误,请与我们取得联系,我们将尽最大努力纠正或解决所有错误。

Cheers!

干杯!

翻译自: https://medium.com/@ultimate_guy/a-simple-real-world-example-of-nothing-in-kotlin-33f5d7d01fa6

kotlin 例子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值