【问题标题】:Override static var in a child Class Swift覆盖子类 Swift 中的静态变量
【发布时间】:2016-03-03 23:40:14
【问题描述】:

为了分解我的代码,我想从 Child 类中设置一个 stringKey,我将在父类的类 func 中获得它:

Chair.request();
Table.request();

class Furniture: NSObject {

    static let requestKey : String!

    class func request(){

        print("class key => \(self.requestKey)")
        ...
    }
}

class Chair: Furniture {
    static let requestKey : String = "jsonchairs"
} 

class Table: Furniture {
    static let requestKey : String = "tables"
} 

当然,我有预编译的错误信息

属性不会覆盖其超类中的任何属性

是否有解决方案,或者我需要将密钥作为参数传递?像这样:

Chair.request(key : "jsonchairs" );
Table.request(key : "tables" );

【问题讨论】:

  • 这里为什么需要静态?您可以拥有一个成员变量,例如家具类型,并且可以在相应子类的初始化程序中覆盖它。
  • 实例化任何类,我只使用类方法...

标签: swift static overriding var


【解决方案1】:

刚刚遇到同样的问题。使用计算属性 - 这些可以被覆盖。

基类:

class BaseLanguage {
    class var language: String {
        return "Base"
    }

    static func getLocalized(key: String) -> String {
        print("language: \(language)");
    }
}

儿童班:

class German: BaseLanguage {
    override class var language: String {
        return "de"
    }
}

如果由于某种原因你不能使用计算属性,你总是可以将变量属性包装在私有单例中。该类将外部接口公开为静态的,但在其内部具有对其实例的静态私有引用。您可以在 init 方法中更改任何属性的值(只要它是变量)。

【讨论】:

  • 只需使用class var 而不是static var,以允许在子类中覆盖。
【解决方案2】:

您可以为此使用协议。只需让它们都符合 RequestKeyProtocol fi 示例,然后在每种情况下都实现它。

protocol RequestKeyProtocol {
 var requestKey: String
}




 class myClass: RequestKeyProtocol {
   var requestKey = "myKey"
   }

如果您需要默认值,请查看协议扩展。 Take a look at this year WWDC video about protocols as well.

【讨论】:

  • 我认为这 (+1) 是在 Swift 中解决这个问题的正确方法。使用协议来声明变量。我可能还会使用协议扩展来实现request 方法。
【解决方案3】:

我相信 vale 是正确的,在这种情况下通常会考虑协议。除了为requestKey 提供协议定义之外,我还将实现request 作为协议的默认实现:

// define Furniture protocol

protocol Furniture {
    static var requestKey: String { get }
    static func request()
}

// implement default implementation in extension

extension Furniture {
    static func request() {
        print("class key => \(self.requestKey)")
    }
}

// both Chair and Table conform to this protocol

class Chair: Furniture {
    static let requestKey = "jsonchairs"
}

class Table: Furniture {
    static let requestKey = "tables"
} 

注意,我假设 Furniture 基类并不是真正需要的,所以我选择了它作为我的协议。你只需要决定你是否真的需要这个Furniture 基类。当我从面向对象编程过渡到面向协议编程时,我的经验法则是是否可以有这种Furniture 类型的具体实例,或者它是否更像是一种抽象/虚拟类型,仅用于定义一些共享最终将被实例化的其他类型的行为(即ChairTable 类型)。

如果Furniture 确实是一个具体的类型,那么你必须找到一种方法来实现你想要的,而不使用static 类型或方法,因为你不能覆盖静态。如果您向我们展示您如何使用除了 ChairTable 类型之外的 Furniture 类型,我们可能会帮助您以不需要 static 的方式重构它方法/类型。

但是如果Furniture 不是一个具体的类型,那么我建议你自己努力,看看你是否可以通过协议完成你需要的一切。当你从面向对象编程转变为面向协议编程时,你需要一点时间来理解它。只是不要太硬。有关详细信息,请参阅 WWDC 2015 video Protocol-Oriented Programming in Swift 或等效的 WWDC 2016 video Protocol and Value Oriented Programming in UIKit Apps

顺便说一句,即使您采用这种面向协议的模式,我也不会倾向于在您的特定示例中使用 static 类型/方法,但这是一个单独的问题。上述面向协议的模式同样适用于 static 方法和实例方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 2013-10-27
    • 1970-01-01
    • 2018-12-08
    相关资源
    最近更新 更多