[英]How do I subclass a struct in Swift?
struct MyRect : CGRect {...}
是否有可能迅速对结构进行子类化?
我已经在苹果官网上找到了一个例子:这个例子扩展了 CGRect 结构来包含一个计算区域属性:
extension CGRect {
var area: CGFloat {
return width * height
}
}
let rect = CGRect(x: 0.0, y: 0.0, width: 10.0, height: 50.0)
let area = rect.area
如何定义结构的子类?
在 Swift 中无法对struct
进行子类化,只能对类进行子类化。 extension
不是子类,它只是在现有struct
上添加附加功能,这与 Objective-C 中的类别相当。
请在此处查看Apple Swift 文档以了解struct
和class
之间的差异。
你不能在 Swift 中对结构进行子类化,因为这就是 Swift 的设计方式。 一个人可能会争辩说他们不应该这样做并没有内在的原因,但另一个人可能会很容易地争辩说有。 通过禁止它,结构是类的轻量级替代品(在元数据、调度、固定大小等方面是轻量级的)。 如果每个无处不在的数据类型,如整数和字符串(它们是结构)都必须携带额外的包袱(使它们可进行子类化),那么您可以想象与现在相比,该语言可能变得多么不快。
也就是说,在某种意义上,您可以通过创建一个简单地分发您想要子类化的结构的结构来模拟子类化。 例如,如果您想对Calendar
进行子类化(您不能这样做,因为它是一个结构),您可以创建一个结构来实例化日历、配置它并返回它。
struct CustomCalendar {
let american1: Calendar = {
var c = Calendar(identifier: .gregorian)
c.timeZone = .current
c.locale = Locale(identifier: "en_US_POSIX")
return c
}()
static let american2: Calendar = {
var c = Calendar(identifier: .gregorian)
c.timeZone = .current
c.locale = Locale(identifier: "en_US_POSIX")
return c
}()
static func american3() -> Calendar {
var c = Calendar(identifier: .gregorian)
c.timeZone = .current
c.locale = Locale(identifier: "en_US_POSIX")
return c
}
}
let customCal = CustomCalendar()
let cal1 = customCal.american1
let cal2 = CustomCalendar.american2
let cal3 = CustomCalendar.american3()
在这种情况下,您如何出售结构(作为静态属性、通过静态函数、基于实例等)只是个人喜好的问题,因为它们都会为您提供完全相同的东西。
这有点旧,但我遇到了它,并认为我会发布一个在需要时使用的通用模式。 例如,我正在处理的一个应用程序需要使用 AspectRatios 做一些工作。 好吧,在我看来,AspectRatio 只不过是具有一些附加功能的 CGSize。 我想要一个 AspectRatio 和一个 CGSize 之间的一点分离,所以我创建了一个 TypeAlias,然后创建了一个 TypeAlias 的扩展。
像这样的东西:
public typealias AspectRatio = CGSize
public extension AspectRatio {
enum Orientation {
case landscape
case portrait
case square
}
static let square = AspectRatio(width: 1.0, height: 1.0)
static let standard = AspectRatio(width: 4.0, height: 3.0)
static let wideScreen = AspectRatio(width: 16.0, height: 9.0)
static let theater = AspectRatio(width: 21.0, height: 9.0)
static let imax = AspectRatio(width: 1.9, height: 1.0)
func aspectRatio(precision: Int? = nil) -> CGFloat {
let aspectRatio = width / height
guard let precision = precision else {
return aspectRatio
}
let multiplier = pow(10, Double(precision))
let value = (Double(aspectRatio) * multiplier).rounded() / multiplier
return CGFloat(value)
}
var orientation: Orientation {
switch self.aspectRatio() {
case let aspect where aspect > 1.0:
return .landscape
case let aspect where aspect < 1.0:
return .portrait
default:
return .square
}
}
func flipped() -> AspectRatio {
return AspectRatio(width: height, height: width)
}
...
}
然后我可以轻松定义这样的变量:
var aspectRatio: AspectRatio = .imax
从 Swift 5.1 开始,现在可以执行类似于您要求的操作:使用组合、 KeyPath
和dynamicMemberLookup
。 看看: https : //medium.com/@acecilia/struct-composition-using-keypath-and-dynamicmemberlookup-kind-of-struct-subclassing-but-better-6ce561768612?source=friends_link&sk=da479578032c0b46c1c69114edfb605
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.