使用静态方法时如何获取特定实例

时间:2019-02-14 02:47:39

标签: ios swift inheritance

当我使用静态方法时,我希望得到一个特定的实例。例如:

class Food: NSObject {
    var name: String

    class func initFruit() -> Food? {
        let fruitName = NSStringFromClass(self).components(separatedBy: ".").last! as String

        if "Apple" == fruitName {
            return Apple(name: fruitName)
        } else if "Orange" == fruitName {
            return Orange(name: fruitName)
        }
        return nil
    }

    init(name: String) {
        self.name = name
    }

}

class Apple: Food {
}
class Orange: Food {
}

当我使用以下方法创建Apple实例时:

let apple = Apple.initFruit() as? Apple

如何获取特定的实例苹果而不是使用as? Apple?我想知道如何修改方法:

 static func initFruit() -> Food?

3 个答案:

答案 0 :(得分:4)

您的设计有几个问题,让我尝试列举一下:

  • 基类不应该知道其子类,这是一种不好的做法,并且不能扩展,因为添加新的子类将需要维护基类方法
  • 完全不需要静态方法,至少在问题中所写的形式如此,您可以直接为子类直接调用初始化器

将所有这些放在一边,您可以使用Self作为静态方法的返回类型,这将允许动态结果。

class Food: NSObject {
    var name: String

    class func initFruit() -> Self {
        let fruitName = NSStringFromClass(self).components(separatedBy: ".").last! as String

        return self.init(name: fruitName)
    }

    required init(name: String) {
        self.name = name
    }

}

class Apple: Food {
}
class Orange: Food {
}

let apple = Apple.initFruit() // is an Apple, no cast needed

答案 1 :(得分:2)

我认为这不是一个好主意,因为Food是父类,Apple继承了Food。苹果可能知道它的父类原因是延长食品,但食品没有。

因此,如果要通过某个字符串或某个变量创建实例。我建议您采用“工厂模式”

参考在这里: https://medium.com/swift-programming/design-patterns-creational-patterns-factory-pattern-in-swift-d049af54235b

答案 2 :(得分:0)

受问题Generics in Swift - "Generic parameter 'T' could not be inferred的启发,我找到了解决此问题的另一种方法。我添加了一种推断特定类型的方法。

func ascertainFruitType<T>() -> T {
    return self as! T // as! is dangerous
}

然后在下面更改方法initFruit

class func initFruit() -> Self {
    let fruitName = NSStringFromClass(self).components(separatedBy: ".").last! as String

    if "Apple" == fruitName {
        return Apple(name: fruitName).ascertainFruitType()
    } else {
        return Orange(name: fruitName).ascertainFruitType()
    }

}