【问题标题】:Send default argument value to a function?将默认参数值发送给函数?
【发布时间】:2016-10-29 00:49:07
【问题描述】:

TL;DR

如果我有func show(message: String = "Hello"),如何发送默认参数而不省略参数名称? (例如show(message: default)

注意:show() 不是我要找的!详情见下文。


假设我们定义了以下函数:

func makeCreature(color: UIColor, eyeCount: Int = 2, noseCount: Int = 1) -> Creature {
  // ...
}

然后我们还定义了另一个方法,makeCreatures

func makeCreatures(count: Int, color: UIColor) {
  for 1...count {
    makeCreature(color: color)
  }
}

但是,现在我们想要轻松自定义 makeCreatures 的 eyeCount 和 noseCount。一种方法是重新定义参数及其默认值:

解决方案 #1

func makeCreatures(count: Int, color: UIColor, eyeCount: Int = 2, noseCount: Int = 1) {
  for 1...count {
    makeCreature(color: color, eyeCount: eyeCount, noseCount: noseCount)
  }
}

这样做的问题是,如果默认的眼睛数量发生变化,我需要记住在两个地方更新它:makeCreaturemakeCreatures

我希望做的是将方法定义为:

func makeCreatures(count: Int, color: UIColor, eyeCount: Int? = nil, noseCount: Int? = nil)

但是,现在这意味着我必须创建 4 个不同的 if 分支:

解决方案 #2

func makeCreatures(count: Int, color: UIColor, eyeCount: Int? = nil, noseCount: Int? = nil) {
  for 1...count {
    if let eyeCount = eyeCount, let noseCount = noseCount {
      makeCreature(color: color, eyeCount: eyeCount, noseCount: noseCount) 
    } else if let eyeCount = eyeCount {
      makeCreature(color: color, eyeCount: eyeCount)
    } else if let noseCount = noseCount {
      makeCreature(color: color, noseCount: noseCount)
    } else {
      makeCreature(color: color)
    }
  }
}

必须创建 4 个不同的分支有点丑陋且难以理解。有没有更好的方法可以让我得到解决方案#1 的简洁性和#2 的 DRYness?类似的东西:

理想的解决方案?

func makeCreatures(count: Int, color: UIColor, eyeCount: Int? = nil, noseCount: Int? = nil) {
  for 1...count {
    makeCreature(color: color, 
      eyeCount: eyeCount ?? default, 
      noseCount: noseCount ?? default)
  }
}

其中default 表示使用makeCreature 中定义的默认参数值(即2 用于eyeCount1 用于noseCount)。

如果没有,还有哪些其他解决方案可以帮助我实现这一目标?

【问题讨论】:

  • 只需在两个函数都可用的某个范围内设置两个 Int 常量,并将它们设为函数的默认参数。也不需要选项。
  • 我很好奇为什么你的makeCreature 不是Creature 的初始化器。

标签: swift default-arguments


【解决方案1】:

为了完整起见,还有另一个类似于Alexander's 的解决方案。

您可以创建一个结构来保存生物的属性:

struct Attributes {
  let color: UIColor
  let eyeCount: Int = 2
  let noseCount: Int = 1
}

然后重新定义函数来接受属性:

func makeCreature(attributes: Attributes) -> Creature {
  // ...
}

func makeCreatures(count: Int, attributes: Attributes) {
  for 1...count {
    makeCreature(color: color, attributes: attributes)
  }
}

这允许您在两个函数中使用默认值:

// uses 2 eyes (default), and 2 noses
makeCreature(attributes: Attributes(color: .purple, noseCount: 2))

// use 10 eyes, and 1 nose (default)
makeCreatures(count: 3, attributes: Attributes(color: .blue, eyeCount: 10))

【讨论】:

    【解决方案2】:

    这不是您正在寻找的,但您可以为此使用构建器模式:

    struct Creature {
        let color: UIColor
        let eyeCount: Int
        let noseCount: Int
    }
    
    struct CreatureBuilder {
        var color: UIColor?
        var eyeCount: Int = 2 //store defaults here
        var noseCount: Int = 1
    
        func build() -> Creature {
            guard let color = color else { fatalError("Creatures need a color!") }
    
            return Creature(color: color, eyeCount: eyeCount, noseCount: noseCount)
        }
    }
    
    func makeCreatures(count: Int, color: UIColor, eyeCount: Int? = nil, noseCount: Int? = nil) {
        var builder = CreatureBuilder()
        builder.color = color;
        if let eyeCount = eyeCount { builder.eyeCount = eyeCount } //override defaults only for non-nil params
        if let noseCount = noseCount { builder.noseCount = noseCount }
    
        for _ in 1...count {
            let creature = builder.build() //TODO: do something with the creature.
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 1970-01-01
      • 2011-02-20
      • 2011-04-09
      • 1970-01-01
      • 2015-01-28
      • 1970-01-01
      相关资源
      最近更新 更多