简体   繁体   English

Swift - 具有特定类类型的数组

[英]Swift - Array with specific class type

How can i create array which will hold objects belonging a specific class.我如何创建数组来保存属于特定类的对象。

class BaseObject {}

class Derived1: BaseObject {}
class Derived2: BaseObject {}
class Derived2: BaseObject {}

I need to create array in which will hold only Object derived from BaseObject我需要创建一个数组,其中将只保存从BaseObject派生的对象

Something like - var array : [BaseObject.Type] = []类似 - var array : [BaseObject.Type] = []

Is there a way to specify this ?有没有办法指定这个?

Also, I should be able to use it something like this另外,我应该能够像这样使用它

if let derived1 = object as? [Derived1] {

}
else if let derived2 = object as? [Derived2] {

}

You can obviously define your array as an array of BaseObject :您显然可以将数组定义为BaseObject数组:

var objects: [BaseObject] = []  // or `var objects = [BaseObject]()`

But it's going to let you create a heterogenous collection (of either BaseObject or Derived1 or Derived2 or of any other subclass).但它会让你创建一个异构集合( BaseObjectDerived1Derived2或任何其他子类)。 That's a core OO design concept (the Liskov substitution principle ) that any subclass of BaseObject should (and will) be permitted.这是一个核心 OO 设计概念( Liskov 替换原则),任何BaseObject子类BaseObject应该(并且将会)被允许。

If all you want is to say that you can only have an array of one of the subtypes, you can obviously just define your array as such, eg:如果你只想说你只能有一个子类型的数组,你显然可以这样定义你的数组,例如:

var objects: [Derived1] = []

That will obviously allow only Derived1 objects (and any subclasses of Derived1 .这显然只允许Derived1对象(以及Derived1任何子类。


90% of the time, the above is sufficient.在 90% 的情况下,以上就足够了。 But in some cases, you might needs some collection with methods that require some inherited base behavior, but for which you don't want to allow heterogenous collections.但在某些情况下,您可能需要一些带有需要继承的基本行为的方法的集合,但您不想允许异构集合。 In this case, I might consider a more protocol-oriented pattern:在这种情况下,我可能会考虑更面向协议的模式:

  1. Bottom line, should we be subclassing, or should we be using a protocol-oriented approach?最重要的是,我们应该子类化,还是应该使用面向协议的方法? Ie is BaseObject actually something you'll instantiate for its own purposes, or is it there merely to define some common behavior of the subclasses.BaseObject实际上是您为了自己的目的而实例化的东西,或者它只是为了定义子类的一些常见行为。 If the latter, a protocol might be a better pattern, eg:如果是后者,协议可能是更好的模式,例如:

     protocol Fooable { func foo() } // if you want, provide some default implementation for `foo` in an // protocol extension extension Fooable { func foo() { // does something unique to objects that conform to this protocol } } struct Object1: Fooable {} struct Object2: Fooable {} struct Object3: Fooable {}

    This yields the sort of behavior that you may have been using in your more OO approach, but using protocols.这产生了您可能在更多面向对象的方法中使用的那种行为,但使用了协议。 Specifically, you write one foo method that all of the types that conform to this protocol, eg, Object1 , Object2 , etc., can use without having to implement foo themselves (unless, of course, you want to because they need special behavior for some reason).具体来说,您编写了一个foo方法,所有符合此协议的类型(例如Object1Object2等)都可以使用而无需自己实现foo (当然,除非您想这样做,因为它们需要特殊的行为)一些理由)。

  2. Because this eliminates the subclassing, this then opens the door for the use of generics and protocols that dictate some generalized behavior while dictating the homogenous nature of the members.因为这消除了子类化,所以这为使用泛型和协议打开了大门,这些泛型和协议规定了一些通用的行为,同时规定了成员的同质性。 For example:例如:

     struct FooCollection<T: Fooable> { private var array = [T]() mutating func append(_ object: T) { array.append(object) } // and let's assume you need some method for your collection that // performs some `Fooable` task for each instance func fooAll() { array.forEach { $0.foo() } } }

    This is a generic which is a homogenous collection of objects that conform to your protocol.这是一个泛型,它是符合您的协议的同构对象集合。 For example, when you go to use it, you'd declare a particular type of Fooable type to use:例如,当你去使用它时,你会声明一个特定类型的Fooable类型来使用:

     var foo = FooCollection<Object1>() foo.append(Object1()) // permitted foo.append(Object2()) // not permitted foo.fooAll()

Now, I only went down this road because in comments elsewhere, you were inquiring about generics.现在,我只是走这条路,因为在其他地方的评论中,您正在询问泛型。 I'd personally only go down this road if the (a) collection really needed to be homogenous;如果(a)系列真的需要同质化,我个人只会走这条路; and (b) the collection also wanted to implement some shared logic common to the protocol. (b) 该集合还希望实现协议共有的一些共享逻辑。 Otherwise, I'd probably just stick with a simple [Derived1] (or [Object1] ).否则,我可能会坚持使用简单的[Derived1] (或[Object1] )。 The above can be powerful when needed, but is overkill for simpler situations.以上在需要时可以很强大,但对于更简单的情况来说是过度的。

For more discussion about protocol oriented programming, the homogenous vs heterogenous behavior, traditional stumbling blocks when you're coming from a traditional OO mindset, I'd refer you to the WWDC 2015 video, Protocol-Oriented Programming in Swift , or it's 2016 companion video that builds upon the 2015 video.有关面向协议编程、同构与异构行为、传统 OO 思维模式下的传统绊脚石的更多讨论,我会向您推荐 WWDC 2015 视频, Swift 中的面向协议编程,或者它的2016 伴侣视频是建立在2015年的视频。

Finally, if you have any additional questions, I'd suggest you edit your question providing details on a practical problem that you're trying to solve with this pattern.最后,如果您有任何其他问题,我建议您编辑您的问题,提供有关您尝试使用此模式解决的实际问题的详细信息。 Discussions in the abstract are often not fruitful.抽象的讨论往往没有成果。 But if you tell us what the actual problem you're trying to solve with the pattern in your question, it will be a far more constructive conversation.但是,如果您告诉我们您试图用问题中的模式解决的实际问题是什么,这将是一次更具建设性的对话。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM