在 Swift 中使用具有关联值的枚举是否违反里氏替换原则?
Does using enum with associated value in Swift violate Liskov Substitution Principle?
enum WeatherType {
case cloudy(coverage: Int)
case sunny
case windy
}
我刚刚在 Swift 教程中看到了这一点,我无法相信他们允许您这样做。现在,每当我打开那个枚举时,我都要为 cloudy
!
创建一个特例
Now, whenever I switch on that enum
, I gotta create a special case for cloudy
!
事实并非如此,原因如下:
- 您可以忽略
cloudy
,将其与 default
和 捆绑在一起
- 模式匹配 可让您阅读
cloudy
的 coverage
属性,同时将 cloudy
本身视为一个案例。
- 当您阅读 属性
coverage
时,您可以选择忽略它或采取行动。
这里有一些例子:
switch weatherType {
case .Cloudy(_):
print("It is cloudy. I ignore the coverage.")
...
}
switch weatherType {
case .Cloudy(let coverage):
print("It is cloudy. Coverage is \(coverage).")
...
}
switch weatherType {
case .Cloudy(let coverage) where coverage > 80:
print("It is very cloudy.")
case .Cloudy(let coverage) where coverage < 20:
print("It is slightly cloudy.")
case .Cloudy(_):
print("It is cloudy.")
...
}
Liskov Substitution Principle 与子类化有关。枚举不允许子类化,因此在这里不适用。
我不确定你反对为 cloudy
创建一个特例的原因是什么;如果您想专门处理这种情况,则无论如何都必须在 switch
中这样做。获取关联值的额外语法非常简单。
let weather = WeatherType.cloudy(coverage: 17)
switch weather {
case .sunny:
print("sunny")
case .windy:
print("windy")
case .cloudy(let coverage):
print("cloudy with coverage \(coverage)")
}
你什么都不"gotta"做。如果您不关心承保范围是什么,就不要问承保范围是什么。不在乎阴天,就别问阴天。为具有关联值的案例编写开关的方式没有什么特别之处。
假设我们有这个:
let weather = WeatherType.cloudy(coverage:1)
那么这是完全合法的:
switch weather {
case .sunny:
print("it is sunny")
default:
print("I guess it's cloudy, or maybe windy")
}
这也是!
switch weather {
case .cloudy:
print("it is cloudy")
default:
print("I guess it's sunny, or maybe windy")
}
也没有任何法律要求您编写 switch 语句。如果你只是想知道weather
是否是.cloudy
,只要问:
if case .cloudy = weather {
print("yes it is cloudy")
} else {
print("I guess it's sunny, or maybe windy")
}
如果您确实碰巧想知道coverage
是什么,您仍然不需要编写 switch 语句:
if case let .cloudy(cov) = weather {
print("yes it is cloudy, in fact it is \(cov)")
} else {
print("I guess it's sunny, or maybe windy")
}
你不能做的是应用==
。这不会编译:
if weather == .sunny { // error
就此而言,是的,具有关联值的枚举与没有关联值的枚举的行为不同(如果这是您要问的)。
enum WeatherType {
case cloudy(coverage: Int)
case sunny
case windy
}
我刚刚在 Swift 教程中看到了这一点,我无法相信他们允许您这样做。现在,每当我打开那个枚举时,我都要为 cloudy
!
Now, whenever I switch on that
enum
, I gotta create a special case forcloudy
!
事实并非如此,原因如下:
- 您可以忽略
cloudy
,将其与default
和 捆绑在一起
- 模式匹配 可让您阅读
cloudy
的coverage
属性,同时将cloudy
本身视为一个案例。 - 当您阅读 属性
coverage
时,您可以选择忽略它或采取行动。
这里有一些例子:
switch weatherType {
case .Cloudy(_):
print("It is cloudy. I ignore the coverage.")
...
}
switch weatherType {
case .Cloudy(let coverage):
print("It is cloudy. Coverage is \(coverage).")
...
}
switch weatherType {
case .Cloudy(let coverage) where coverage > 80:
print("It is very cloudy.")
case .Cloudy(let coverage) where coverage < 20:
print("It is slightly cloudy.")
case .Cloudy(_):
print("It is cloudy.")
...
}
Liskov Substitution Principle 与子类化有关。枚举不允许子类化,因此在这里不适用。
我不确定你反对为 cloudy
创建一个特例的原因是什么;如果您想专门处理这种情况,则无论如何都必须在 switch
中这样做。获取关联值的额外语法非常简单。
let weather = WeatherType.cloudy(coverage: 17)
switch weather {
case .sunny:
print("sunny")
case .windy:
print("windy")
case .cloudy(let coverage):
print("cloudy with coverage \(coverage)")
}
你什么都不"gotta"做。如果您不关心承保范围是什么,就不要问承保范围是什么。不在乎阴天,就别问阴天。为具有关联值的案例编写开关的方式没有什么特别之处。
假设我们有这个:
let weather = WeatherType.cloudy(coverage:1)
那么这是完全合法的:
switch weather {
case .sunny:
print("it is sunny")
default:
print("I guess it's cloudy, or maybe windy")
}
这也是!
switch weather {
case .cloudy:
print("it is cloudy")
default:
print("I guess it's sunny, or maybe windy")
}
也没有任何法律要求您编写 switch 语句。如果你只是想知道weather
是否是.cloudy
,只要问:
if case .cloudy = weather {
print("yes it is cloudy")
} else {
print("I guess it's sunny, or maybe windy")
}
如果您确实碰巧想知道coverage
是什么,您仍然不需要编写 switch 语句:
if case let .cloudy(cov) = weather {
print("yes it is cloudy, in fact it is \(cov)")
} else {
print("I guess it's sunny, or maybe windy")
}
你不能做的是应用==
。这不会编译:
if weather == .sunny { // error
就此而言,是的,具有关联值的枚举与没有关联值的枚举的行为不同(如果这是您要问的)。