何时使用类型别名?

问题描述 投票:0回答:3

到目前为止,我了解到 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
3个回答
29
投票

实际上,毫无疑问,为字符串创建类型别名:

typealias MyString = String
不会那么有用,(我还假设为具有特定键/值类型的字典声明类型别名:
typealias CustomDict = Dictionary<String, Int>
可能会对你没那么有用。

但是,当涉及到复合类型时,您肯定会注意到类型别名的好处。

示例:

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

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(..., ..., ...)
        }
    }

    // ...
}

如您所见,方法签名看起来真的很乏味!这两种方法都带有

success
failure
参数,它们都是带有参数的闭包;此外,为了实现类似的功能,保持复制粘贴参数并不符合逻辑。

针对这种情况实施

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(..., ..., ...)
        }
    }

    // ...
}

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


此外,您可能想查看我发布的关于它的媒体故事


1
投票

对我来说使用类型别名的常见方法是使用闭包:

typealias VoidClosure = () -> Void

func updateFrom(completion: @escaping VoidClosure) { }


0
投票

在 Swift 中,对我来说很奇怪,他们将它用于简单类型,例如:

typealias CLLocationSpeed = Double

https://developer.apple.com/documentation/corelocation/cllocationspeed

在 Kotlin 中更有意义:

类型别名为现有类型提供替代名称。如果类型名称太长,您可以引入一个不同的较短名称并使用新名称。

缩短长泛型类型很有用。例如,缩小集合类型通常很诱人:

typealias NodeSet = Set<Network.Node>

typealias FileTable<K> = MutableMap<K, MutableList<File>>

您可以为函数类型提供不同的别名:

typealias MyHandler = (Int, String, Any) -> Unit

typealias Predicate<T> = (T) -> Boolean

您可以为内部类和嵌套类使用新名称:

class A {
    inner class Inner
}
class B {
    inner class Inner
}

typealias AInner = A.Inner
typealias BInner = B.Inner

类型别名不会引入新类型。它们相当于相应的底层类型。当您在代码中添加

typealias Predicate<T
并使用
Predicate<Int>
时,Kotlin 编译器始终将其扩展为
(Int) -> Boolean
。因此,只要需要通用函数类型,您就可以传递您类型的变量,反之亦然:

typealias Predicate<T> = (T) -> Boolean
​
fun foo(p: Predicate<Int>) = p(42)
​
fun main() {
    val f: (Int) -> Boolean = { it > 0 }
    println(foo(f)) // prints "true"
​
    val p: Predicate<Int> = { it > 0 }
    println(listOf(1, -2).filter(p)) // prints "[1]"
}
© www.soinside.com 2019 - 2024. All rights reserved.