【问题标题】:Base class static method returns type of subclass in Swift基类静态方法在 Swift 中返回子类的类型
【发布时间】:2019-10-26 02:22:49
【问题描述】:

我想要一个返回子类类型数组的基类静态方法。这是我当前的实现。它有效,但我有一个小问题。

class Animal {
    required init() { }
    public static func generateMocks<T: Animal>() -> [T] {
        var mocks: [T] = []
        // some implementation goes here...
        for _ in 0..<10 {
            mocks.append( T() )
        }
        //
        return mocks
    }
}


let myMockAnimals: [Animal] = Animal.generateMocks() // this gives me type [Animal]

class Dog: Animal {
    // dog things
    var isCute = true
}

let myMockDogs: [Dog] = Dog.generateMocks() // this gives me type [Dog]
print(myMockDogs.first?.isCute) // true

/* My problem is that it is very annoying to have to declare my
   myMockDogs variable as type "[Dog]". I would like it to
   automatically infer this type. Like this: */

let myMockDogs2 = Dog.generateMocks() // oh no! It gives me type [Animal]
print(myMockDogs2.first?.isCute) // error! Value of type 'Animal' has no member 'isCute'
if let dog = myMockDogs2.first! as Dog { // error! 'Animal' is not convertible to 'Dog';
    print(dog)
}

所以我的通用静态函数generateMocks 能够在我指定我期望的对象类型时返回正确的子类,比如let myMockDogs2: [Dog] =...,但是当我放弃我期望的显式类型时,就像let myMockDogs2 =... 然后它突然回到使用 Animal 作为泛型函数的类型,从而产生一个数组 [Animal]

有没有办法修改generateMocks 函数,这会导致let myMockDogs2 = Dog.generateMocks() 自动将类型Dog 用于通用T

您也可以将此代码复制到 Playground 中!它在那里工作!我真的很害怕没有解决方案,但也许那里的 Swift 天才有一个想法。

【问题讨论】:

  • 你不能返回 Self 的数组,因为你会得到错误:“'Self' 仅在协议中可用或作为类中方法的结果;你做到了吗?是“动物”的意思吗?”您可以只返回一个 singular Self 对象,但不能返回一个 array 对象。
  • @matt 我不确定你的意思,但是在 Animal 中的静态方法的上下文中 self 很可能总是指 Animal 即使被 Dog 静态调用...

标签: swift generics types


【解决方案1】:

一种可能的解决方案是协议扩展

protocol Animal {
    init()
    static func generateMocks() -> [Self]
}

extension Animal {
    static func generateMocks() -> [Self] {
        var mocks: [Self] = []
        // some implementation goes here...
        for _ in 0..<10 {
            mocks.append( Self() )
        }
        //
        return mocks
    }
}

struct Dog: Animal {
    // dog things
    var isCute = true
}

let myMockDogs = Dog.generateMocks()
print(myMockDogs.first?.isCute) // true

【讨论】:

  • 不错!我希望它是一个类,而不是一个结构,但我已经成功了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2021-07-26
  • 1970-01-01
  • 2010-12-19
  • 1970-01-01
相关资源
最近更新 更多