有什么具体的例子使用Any类型是一个很好的解决方案? [英] Are there any concrete examples when using the Any type is a good solution?

查看:141
本文介绍了有什么具体的例子使用Any类型是一个很好的解决方案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们都知道swift有一个强大的类型系统,因此我倾向于使用这个系统,我的优势:)



这里是苹果说的使用任何类型:


为Any和AnyObject类型转换



Swift提供了两个特殊类型别名,用于处理非特定的
类型:



AnyObject可以表示任何类类型的实例。任何可以
表示任何类型的实例,包括函数类型。
注意



只有当您明确需要它们提供的行为和
功能时才使用Any和AnyObject。


我不知道知道它是我,但我认为代码开始闻到使用这些(这可能是我缺乏使用它们的经验) - 我知道AnyObject是需要/有用的与Objective-C的交互,所以我得到一个实用AnyObject的使用。



所以我想知道什么具体的例子代表了Any类型的一个很好的使用。



它可以用于将未知内容传递到POST请求构造函数方法,其中该方法可以安全地使用可选链来检查未知内容。



Apple的示例来自



在定义内容时,应始终使用最具描述性的类型,因为 Any 的抽象性质,总是是一个更具描述性的类型 - 在这种情况下,应该已经使用了 String



现在让我们考虑数组。正如你所说,苹果表明你可以使用任何数组来混合不同的类型。

  var things = [Any]()

things.append(0)
things.append(0.0)
things.append b $ b things.append(3.14159)
things.append(hello)
things.append(Movie(name:Ghostbusters,director:Ivan Reitman))

很好。但这个数组实际上代表什么?



如果我们尝试使用某个元素做某事...





我们不能。它可以是任何 - 所以我们不能做任何事情。当然,我们可以使用开关如果语句来处理不同的可能性,我们会成功地把我们的数组拆分成不同的类型。那么使用 [Any] 开始的点是什么?



数组应该总是表示一个集合相关数据。如果元素没有共同的东西,没有数组的点。如果数组可以存储的不同类型具有共同的功能,那么你应该使用这个常用的功能定义一个协议:

  protocol ACommonProtocol {
//定义公共功能
}

数组可以存储到它:

 扩展Int:ACommonProtocol {} 
扩展Double:ACommonProtocol {}
extension String:ACommonProtocol {}
extension电影:ACommonProtocol {}

可以是 [ACommonProtocol] 类型。这是从任何起的显着改进,我们缩小了元素可以缩减到4的具体类型,现在我们可以使用任何我们在协议中定义的没有类型转换的元素的通用功能。我们的元素现在也显式地相关,实际上给数组一些意义(假设协议代表一个有意义的概念)。



数组可以存储的类型不具有任何通用功能(但是仍然以某种有意义的方式相关) - 然后表达这种关系的另一种方式是通过使用枚举和相关的值:

  //显然这个枚举名称
enum IntDoubleStringOrMovie {
case int(Int)
case double(Double)
case string(String)
case movie(Movie)
}

现在我们的数组可以是 [IntDoubleStringOrMovie] - 它具有允许我们使用穷尽的开关以确定元素类型的额外好处:

  for数组{
开关元素{
case let .int(int):
print(int)
case let .double (double):
print(double)
case let .string(string):
print(string)
case let .movi​​e(movie):
print电影)
}
}

因此,必须在Swift中使用 [Any] 。如果你发现自己处于使用 [Any] 的情况,你应该重新考虑你的数据结构。无论是涉及将数组分解为子数组,使元素符合公共协议(如果它们具有共同的功能),使用带有关联值的枚举(如果它们没有共同的功能)或者使用不同的集合类型,完全取决于你。



虽然,所有的说,有一个边缘情况,我错过了 - 即函数和元组。您不能将函数或元组与自定义协议相一致,因此上述解决方案将无法使用它们。



但是,如果你发现自己混合了元组或不同的函数类型在数组 - 你应该肯定会重新思考你的逻辑。而不是元组,使用结构或枚举与相关联的值。对于函数,你应该最有可能在结构或类中使用关联类型的泛型和/或协议。



但是与Objective-C的接口? h3>

任何有时是与Objective-C的劣等类型系统桥接所必需的,因此你可能会发现自己使用 [Any] 使用Objective-C API,这是可以接受的(虽然 Objective-C的轻量级泛型桥接到Swift,它应该是不常见的)。



我想说的只是一旦你回到你的Swift逻辑,你应该总是转换 [Any] 通过类型转换回到有意义的数组类型,或将其解包到更合适的数据结构中。你不应该牺牲Swift中的类型安全,因为Objective-C在这方面缺乏。



但是 [AnyObject]



AnyObject $ c>在纯Swift。它唯一保证是它是一个类。但是,从Swift 3开始, 任何都可以桥接到目标-C 通过在 _SwiftValue 中加框。因此, [AnyObject] [Any] 一样(如果不是更多 $ c>。


We all know that swift has a strong type system, and as such I lean towards using this system to my advantage :)

Here's what Apple has to say about using the Any type:

Type Casting for Any and AnyObject

Swift provides two special type aliases for working with non-specific types:

AnyObject can represent an instance of any class type. Any can represent an instance of any type at all, including function types. NOTE

Use Any and AnyObject only when you explicitly need the behavior and capabilities they provide. It is always better to be specific about the types you expect to work with in your code.

I don't know if it's me, but I kind of think the code starts to smell when using these (This maybe my lack of experience using them) - I know AnyObject is required/useful for interacting with Objective-C so I get that there is a practical nature to AnyObject's use.

So I wanted to know what concrete examples represent a good use of the Any type.

For example is it could be used to pass unknown content to a POST request constructor method where the method could safely use optional chaining to examine the unknown content.

Apple's example from the Swift Programming Language (Swift 2.2)

Any

Here’s an example of using Any to work with a mix of different types, including function types and non-class types. The example creates an array called things, which can store values of type Any:

var things = [Any]()

things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
things.append({ (name: String) -> String in "Hello, \(name)" })

解决方案

When should I use [Any]?

Any is an abstract type that all other types implicitly conform to. Therefore because it could be anything – it must be guaranteed to do nothing.

For that very reason, typing a variable as Any is nonsensical. If I define this:

let itCouldBeAnything : Any = "Actually it's a string"

It now can't do anything (without type casting):

You should always use the most descriptive type available when defining something, and because of Any's abstract nature, there will always be a more descriptive type available – in this case, String should've been used.

Now let’s think about arrays. As you say, Apple demonstrates that you can use an array of Any to mix together different types.

var things = [Any]()

things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))

Great. But what does this array actually represent? It’s just a collection of junk – the programming equivalent of the backseat of my car.

If we try and do something with one of the elements...

We can’t. It could be anything – so we can’t do anything with it. Sure, we can type cast the elements with a switch or if statement to handle the different possibilities – but all we’ll succeed in doing there is splitting our array back into distinct types. So what was the point in using [Any] to begin with?

An array should always represent a collection of related data. There’s no point of an array if the elements share nothing in common. If the different types that the array can store have common functionality, then you should define a protocol with this common functionality:

protocol ACommonProtocol {
    // define common functionality
}

We can then conform the types that the array can store to it:

extension Int : ACommonProtocol {}
extension Double : ACommonProtocol {}
extension String : ACommonProtocol {}
extension Movie : ACommonProtocol {}

Now our array can be of type [ACommonProtocol]. This is a significant improvement from Any, we’ve narrowed the concrete types that the elements could be down to 4 – and we can now use any common functionality that we define in the protocol on the elements without type-casting. Our elements also are now explicitly related, which actually gives the array some meaning (assuming the protocol represents a meaningful concept).

If the different types that the array can store don't have any common functionality (but are still related in some meaningful way) – then another way of expressing this relationship is through using an enum with associated values:

// obviously this enum (and possibly its cases) should have a far better names
enum IntDoubleStringOrMovie { 
    case int(Int)
    case double(Double)
    case string(String)
    case movie(Movie)
}

Now our array can be of type [IntDoubleStringOrMovie] – which has the added benefit of allowing us to use an exhaustive switch in order to determine the element type:

for element in array {
    switch element {
    case let .int(int):
        print(int)
    case let .double(double):
        print(double)
    case let .string(string):
        print(string)
    case let .movie(movie):
        print(movie)
    }
}

So for this reason, you should never ever have to use [Any] in Swift. If you ever find yourself in a situation of using [Any], you should be re-considering your data structure. Whether that involves splitting the array up into sub-arrays, conforming the elements to a common protocol (if they have common functionality), using an enum with associated values (if they have no common functionality) or using a different collection type altogether, is entirely up to you.

Although, that all being said, there's an edge case that I've missed out on – namely functions and tuples. You cannot conform functions or tuples to a custom protocol – so the above solution won't work with them.

However, if you find yourself mixing together tuples or functions of different types in an array – you should certainly be re-thinking your logic. Instead of tuples, use structs or enums with associated values instead. For functions, you should most likely be using generics and/or protocols with associated types in a struct or class instead.

But what about interfacing with Objective-C?

Any is sometimes necessary for bridging with Objective-C’s inferior type system – and therefore you may well find yourself using [Any] with Objective-C APIs, which is acceptable (although with the bridging of Objective-C's lightweight generics to Swift, it should be uncommon).

The only thing I would say about this is once you’re back in your Swift logic, you should always convert an [Any] back to a meaningful array type through type casting, or unpacking it into a more appropriate data structure. You shouldn’t sacrifice type safety in Swift just because Objective-C lacks in that regard.

But what about [AnyObject]?

AnyObject is pretty much as vague as Any in pure Swift. The only thing it guarantees is that it’s a class. However, as of Swift 3, anything can be bridged to Objective-C by being boxed in a _SwiftValue. For this reason, [AnyObject] is just as (if not more) questionable as [Any].

这篇关于有什么具体的例子使用Any类型是一个很好的解决方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆