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

Arrays Swift-具有特定类类型的数组,arrays,swift,Arrays,Swift,如何创建包含属于特定类的对象的数组 class BaseObject {} class Derived1: BaseObject {} class Derived2: BaseObject {} class Derived2: BaseObject {} 我需要创建一个数组,其中只包含从BaseObject 类似于-var数组:[BaseObject.Type]=[] 有没有办法具体说明这一点 另外,我应该可以用它来做类似的事情 if let derived1 = object as? [D

如何创建包含属于特定类的对象的数组

class BaseObject {}

class Derived1: BaseObject {}
class Derived2: BaseObject {}
class Derived2: BaseObject {}
我需要创建一个数组,其中只包含从
BaseObject

类似于-
var数组:[BaseObject.Type]=[]

有没有办法具体说明这一点

另外,我应该可以用它来做类似的事情

if let derived1 = object as? [Derived1] {

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

}

显然,您可以将数组定义为
BaseObject
的数组:

var objects: [BaseObject] = []  // or `var objects = [BaseObject]()`
但它将允许您创建一个异构集合(属于
BaseObject
Derived1
Derived2
或任何其他子类)。这是一个核心的OO设计概念,
BaseObject
的任何子类都应该(并且将会)被允许

如果您只想说您只能拥有其中一个子类型的数组,那么您显然可以将数组定义为这样,例如:

var objects: [Derived1] = []
这显然只允许
Derived1
对象(以及
Derived1
的任何子类)


90%的时间,以上是足够的,但是在某些情况下,您可能需要一些需要一些继承的基础行为的方法集合,但是对于那些不希望允许异质集合的方法,在这种情况下,我可能会考虑更多的面向协议的模式:

  • 归根结底,我们是应该进行子类化,还是应该使用面向协议的方法?例如,
    BaseObject
    实际上是为了自己的目的而实例化的,还是只是为了定义子类的一些常见行为。如果是后者,协议可能是更好的模式,例如:

    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 {}
    
    这会产生一种行为,这种行为可能是您在更面向对象的方法中使用的,但使用的是协议。具体地说,您编写了一个
    foo
    方法,所有符合此协议的类型(例如
    Object1
    Object2
    等)都可以使用,而无需自己实现
    foo
    (当然,除非你想这样做,因为他们出于某种原因需要特殊的行为)

  • 因为这消除了子类化,这就为使用泛型和协议打开了大门,这些泛型和协议规定了一些通用行为,同时规定了成员的同质性。例如:

    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() }
        }
    }
    
  • 现在,我只是走这条路,因为在其他地方的评论中,您询问了泛型。我个人只会走这条路,如果(a)集合真的需要同质;和(b)集合还想实现一些协议通用的共享逻辑。否则,我可能只会坚持一个简单的
    [Derived1]
    (或
    [Object1]
    )。在需要时,上述功能可能非常强大,但对于更简单的情况来说,这是一种过火的功能

    有关面向协议编程、同质与异质行为、传统OO思维模式下的传统绊脚石的更多讨论,请参阅WWDC 2015视频,或者是基于2015视频的视频


    最后,如果您还有其他问题,我建议您编辑您的问题,提供您试图用此模式解决的实际问题的详细信息。抽象的讨论通常不会有成果。但如果您告诉我们您试图用问题中的模式解决的实际问题,将是一个更加复杂的问题建设性对话。

    var数组=[BaseObject]()
    我想限制数组使用特定的类对象。如果我用基类创建一个数组,那么我可以添加任何派生类,我更希望根据创建的实例限制它只使用1个派生类型。如果你想限制它只使用1个派生类型–这与问题中的信息相矛盾–使用
    var array=[Derived1]()
    所以基本上你需要一个声明为异构数组的数组,但其行为类似于一个异构数组?这就是我想要的。谢谢@Rob
    var foo = FooCollection<Object1>()
    
    foo.append(Object1())  // permitted
    foo.append(Object2())  // not permitted
    
    foo.fooAll()