【问题标题】:When to use typealias?什么时候使用类型别名?
【发布时间】:2018-05-05 13:09:12
【问题描述】:

到目前为止,我了解 typealias 是现有类型的命名别名。通过使用 typealias,我可以执行以下操作:

typealias MyString = String
var str: MyString?

typealias Strings = [String]
var strs: Strings?

这导致将str 变量声明为字符串,将strs 声明为字符串数组。

即使是自定义类型:

class MyClass {}
typealias MyClsType = MyClass
var myClass: MyClsType

不过,好像有点没用;从逻辑上讲,将var str: MyString? 声明为字符串而不是var str: String? 的目的是什么?更重要的是,var str: String 更具表现力。

【问题讨论】:

标签: swift type-alias


【解决方案1】:

实际上,毫无疑问,为 -let's say- String: typealias MyString = String 创建一个类型别名不会那么有用,(我还假设为具有特定键/值类型的 Dictionary 声明一个类型别名:@987654324 @ 可能对你没那么有用。

但是,当涉及到使用 compound types 时,您肯定会注意到类型别名的好处。

示例:

假设您正在实现管理器,该管理器在其函数中重复使用带有许多参数的闭包:

class MyManager {
    //...

    func foo(success: (_ data: Data, _ message: String, _ status: Int, _ isEnabled: Bool) -> (), failure: (_ error: Error, _ message: String, _ workaround: AnyObject) -> ()) {
        if isSuccess {
            success(..., ..., ..., ...)
        } else {
            failure(..., ..., ...)
        }
    }

    func bar(success: (_ data: Data, _ message: String, _ status: Int, _ isEnabled: Bool) -> (), failure: (_ error: Error, _ message: String, _ workaround: AnyObject) -> ()) {
        if isSuccess {
            success(..., ..., ..., ...)
        } else {
            failure(..., ..., ...)
        }
    }

    // ...
}

如您所见,方法签名看起来真的乏味!这两种方法都采用successfailure 参数,每一个都是带参数的闭包;此外,为了实现类似的功能,保持复制粘贴参数是不合逻辑的。

在这种情况下实施typealias 非常合适:

class MyManager {
    //...

    typealias Success = (_ data: Data, _ message: String, _ status: Int, _ isEnabled: Bool) -> ()
    typealias Failure = (_ error: Error, _ message: String, _ workaround: AnyObject) -> ()

    func foo(success: Success, failure: Failure) {
        if isSuccess {
            success(..., ..., ..., ...)
        } else {
            failure(..., ..., ...)
        }
    }

    func bar(success: Success, failure: Failure) {
        if isSuccess {
            success(..., ..., ..., ...)
        } else {
            failure(..., ..., ...)
        }
    }

    // ...
}

因此它会更具表现力和可读性。


此外,您可能想查看我发布的medium story

【讨论】:

  • typealias for a String 可能有用: - 为读者提供语义含义:let result: Token 而不是 let result: String 会更有意义。 - 如果您每个人都决定从原始值迁移到自定义类型,则类型别名会指导您。例如。如果Token 变成struct,那么编译器会告诉你使用的地方。将typealias 更改为struct 后的第一次编译将按原样编译!
  • 我现在也处于同样的困境中。有一堆很长的泛型类型,如 Results<ObjcA>Results<ObjcE>(以 ObjcX 为例)和一些具有类似形式的字典:[ObjA:[ObjB]] 其中使用诸如 ObjAQueryResult 或 ObjAObjBMapping 之类的名称更有意义,只是更少要键入的代码。但是,我觉得当另一个开发人员接管时,在查找每个类型别名是什么时,会有额外的认知负担,无论多么小,至少直到他们习惯了代码的这个特定部分,这已经很复杂了无论如何。
【解决方案2】:

对我来说,使用 typealias 的常用方法是使用闭包:

typealias VoidClosure = () -> Void

func updateFrom(completion: @escaping VoidClosure) { }

【讨论】:

  • 不仅对于闭包,提及“复合类型”会更准确。您可以在我的答案中查看复合类型的链接,以查看它的含义(类型)。
  • @AhmadF 是的。我完全同意你的看法。当出现一些复杂的类型参数时,它使代码更容易阅读
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
  • 2020-03-05
  • 1970-01-01
  • 2015-04-05
相关资源
最近更新 更多