【问题标题】:How can I get specific instance when I use static method使用静态方法时如何获取特定实例
【发布时间】:2019-02-14 02:47:39
【问题描述】:

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

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?

【问题讨论】:

  • 这可以很容易地使用协议和泛型而不是继承来实现。此外,Apple 的 Swift 指南已转向面向协议,而 imo 这就是你应该这样做的方式。
  • 我同意@Eddie,但是,我想提供一些建议。泛型或继承的全部意义在于您不必知道类型,即AppleOrange。因此,当您初始化时,您可能拥有if(Apple){}, else if(Orange){}...,但之后您可以只使用Food.isEatenFood.jumpIntoCrockPot(),而不必拥有Apple.jumpIntoCrockPot()Orange.jumpIntoCrockPot()。因此,您要创建Food.init() as? Apple 的静态实例的概念删除了Food.init() 的点,因为您现在已将其类型转换为Apple
  • 这只是一个例子。我想知道它是否会从超类静态方法中获取特定的实例。
  • 我不认为你可以使用static,但如果你更改为class func 并在你的子类中覆盖它们,那么你可以返回确切的类。超类不应该知道子类,所以你不能这样做。首选使用工厂类型或泛型类型
  • 你为什么要打电话给initFruit?为什么不直接实例化Apple?静态方法几乎没有提供额外的功能。

标签: ios swift inheritance


【解决方案1】:

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

  • 基类不应该知道它们的子类,这是不好的做法,而且不可扩展,因为添加新的子类需要维护基类方法
  • 根本不需要静态方法,至少在问题中写的形式中,您可以简单地直接调用子类的初始化程序

抛开所有这些,您可以使用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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      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()
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-30
        • 2012-11-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多