我如何在Swift中子类化结构?

时间:2015-11-25 11:05:42

标签: ios xcode swift

struct MyRect : CGRect {...}

是否可以在swift中对子结构进行子类化?

我已经在Apple官方网站上找到了一个例子: 此示例扩展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

如何定义结构的子类?

3 个答案:

答案 0 :(得分:22)

不可能在Swift中继承struct,只能对类进行子类化。 extension不是子类,只是在现有struct上添加了其他功能,这与Objective-C中的类别相当。

请参阅此处的Apple Swift文档,了解structclass之间的差异。

https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-ID82

答案 1 :(得分:2)

从Swift 5.1开始,现在可以执行与您要求的操作类似的操作:使用KeyPathdynamicMemberLookup进行合成。看看:https://medium.com/@acecilia/struct-composition-using-keypath-and-dynamicmemberlookup-kind-of-struct-subclassing-but-better-6ce561768612?source=friends_link&sk=da479578032c0b46c1c69111dfb6054e

答案 2 :(得分:0)

这有点老了,但是我碰到了它,以为我会发布一个在需要时使用的通用模式。例如,我正在处理的一个应用程序需要对AspectRatios做一些工作。好吧,在我看来,AspectRatio就是带有一些附加功能的CGSize。我希望在AspectRatio和CGSize之间稍加分离,所以我创建了TypeAlias,然后创建了TypeAlias的扩展。

类似这样的东西:

#include "boost/type_traits.hpp"
template <bool enable>
struct Foo {

    template <bool e = enable>
    typename boost::enable_if_c<e,void>::type  DoStuff(){}

};

int main(){
    // Compiles
    Foo<true>().DoStuff();
    // Fails
    Foo<false>().DoStuff();
}

然后我可以轻松地定义如下变量:

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