【问题标题】:Avoid type based function calls避免基于类型的函数调用
【发布时间】:2021-04-02 11:49:00
【问题描述】:

下面的代码只是解释程序的示例代码,因为原始代码过于复杂和冗长。我创建了Game 对象的一个​​实例。它可以是三个Cartypes 之一。 MainClass 中的 foo() 函数被调用超过 100 次。 每次调用 foo() 检查对象的类型似乎违反直觉,因为我一开始就知道 obj 的类型。出于性能和简单性的原因,我想避免使用 if 语句。有什么更好的方法来实现这一点?

class Car{
   init(type: CarType, color: String){
      self.type = type
      self.color = color
   }
}

enum Cartypes{
   case sedan
   case pickup
   case coupe
}

class MainClass{
   // this is just an example, it could be any other cartype as well
   let obj = Car(type: .sedan, color: "red")
   
   func foo(){
      if obj.type == .sedan{
         doSedanStuff()
      } else if obj.type == .pickup{
         doPickupStuff()
      } else if obj.type == .coupe{
         doCoupeStuff()
      }
}

【问题讨论】:

    标签: swift performance if-statement types


    【解决方案1】:

    如果您想避免使用if 语句,那么问题是您是否可以将这些“东西”移到类型本身中。

    例如,您可能有一个协议:

    protocol Car {
        func doCarStuff()
    }
    
    struct Sedan: Car {
        let color: String
    
        func doCarStuff() {
            print("go to the grocery store")
        }
    }
    
    struct Pickup: Car {
        func doCarStuff() {
            print("haul stuff to the dump")
        }
    }
    
    struct Coupe: Car {
        func doCarStuff() {
            print("go for spirited drive along the coast")
        }
    }
    

    然后您可以使用该协议,消除 if/switch 语句:

    class MainClass {
        // this is just an example, it could be any other cartype as well
        let obj: Car = Sedan(color: "red")
    
        func foo() {
            obj.doCarStuff()
        }
    }
    

    顺便说一句,我使用了struct,但也适用于class 类型。此外,您可以在基本定义中实现Car 一致性,或者将其添加到扩展中,无论您喜欢哪种方式。

    使用class,您还可以定义基类Car,并使SedanCoupe等类型成为子类。思路是一样的。

    【讨论】:

      【解决方案2】:

      这里的整个组织很奇怪;在我看来,您已经将三个部门划分为类型,而您只需要一个。

      但是,您提出的实际问题的一个答案可能是:这就是子类的用途。每当您发现自己在课堂上检查一种类型时,这都是一种难闻的气味;你应该一直有三种亚型。换句话说,子类类型之间的隐式选择。

      另一种可能性是在注入obj 的同时注入foo 的动作。如果汽车类型的数量是无限制的,这可能更有意义。您仍然需要在类型之间做出选择,但您只需要一次,当类被实例化时:

      class Car {
          let type: CarType
          let color: String
          init(type: CarType, color: String){
             self.type = type
             self.color = color
          }
      }
      enum CarType {
         case sedan
         case pickup
         case coupe
      }
      class MainClass {
          let obj : Car
          var stuff : (() -> ())?
          init(car:Car) {
              self.obj = car
              if obj.type == .sedan{
                  stuff = doSedanStuff
               } else if obj.type == .pickup{
                  stuff = doPickupStuff
               } else if obj.type == .coupe{
                  stuff = doCoupeStuff
               }
          }
         
          func foo(){
              stuff?()
          }
          func doSedanStuff() {}
          func doPickupStuff() {}
          func doCoupeStuff() {}
      }
      

      【讨论】:

        猜你喜欢
        • 2012-03-30
        • 2017-03-17
        • 1970-01-01
        • 2021-02-28
        • 1970-01-01
        • 1970-01-01
        • 2017-03-25
        • 2017-09-23
        • 2017-02-22
        相关资源
        最近更新 更多