【问题标题】:How to store constants at the class level that can be overriden?如何在可以覆盖的类级别存储常量?
【发布时间】:2017-01-08 00:03:15
【问题描述】:

我想用 Swift 编写以下代码:

class A
{
    class let x = 0
    func print_class_property()
    {
        print(type(of: self).x)
    }
}

class B:A
{
    overriding class let x = 1
}

class C:A
{
    overriding class let x = 5
}

A().print_class_property() // 0
B().print_class_property() // 1
C().print_class_property() // 5

当然,这不会编译。

相反,我可以将类属性降级为在子类初始化程序中被覆盖的变量实例属性,但是这A、@ 的每个 实例中的x 分配存储空间987654324@ 或 C 此外,您无法保证 x 在对象的整个生命周期内永远不会更改。

如何在类级别存储可以由子类的所有实例共享的常量?

【问题讨论】:

    标签: swift subclass class-variables


    【解决方案1】:

    不幸的是,Swift(就目前而言)不能拥有可以被覆盖的类存储属性。但可以具有类计算属性,这些属性是可覆盖的。

    你可以这样写:

    class A
    {
        class var x: Int {
            return 0
        }
        func print_class_property()
        {
            print(type(of: self).x)
        }
    }
    
    class B:A
    {
        override class var x: Int {
            return 1
        }
    }
    
    class C:A
    {
        override class var x: Int {
            return 5
        }
    }
    
    A().print_class_property() //->0
    B().print_class_property() //->1
    C().print_class_property() //->5
    

    添加

    如果您不希望进行 cmets 中所述的重新评估,您可能需要其他一些 static 属性。

    例如:

    class A
    {
        class var x: SomeLargeObject {
            struct My {
                static let obj = SomeLargeObject("abc", 0)
            }
            return My.obj
        }
        func print_class_property()
        {
            print(type(of: self).x)
        }
    }
    
    class B:A
    {
        override class var x: SomeLargeObject {
            struct My {
                static let obj = SomeLargeObject("def", 1)
            }
            return My.obj
        }
    }
    
    class C:A
    {
        override class var x: SomeLargeObject {
            struct My {
                static let obj = SomeLargeObject("ghi", 5)
            }
            return My.obj
        }
    }
    

    【讨论】:

    • 这是否相当于每次访问属性时都进行函数调用?
    • True,以及存储的属性。
    • 我一直认为访问存储的属性只包括取消引用指针或类似的东西。但问题是每次访问该属性时都必须重新评估该值,例如存储let x = SomeLargeObject("abc", 5),而不是每次访问该属性时实例化一个new SomeLargeObject
    • @rmaddy,我知道。也许我的话有点太短了,但 that can be override 在这种情况下是一个要求。 static 属性不能被覆盖。
    • @taylorswift,那么它几乎是等价的。稍有不同的是,我的代码中My.obj 的范围严格包含在每个getter 块中。即使在同一个类中(getter 之外),您也无法访问My.obj。类似于私有静态属性和全局变量的区别。
    猜你喜欢
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    相关资源
    最近更新 更多