Swift 如何在初始值设定项中获得受约束泛型的动态分派
下面的代码工作正常:Swift 如何在初始值设定项中获得受约束泛型的动态分派,swift,generics,initializer,dynamic-dispatch,Swift,Generics,Initializer,Dynamic Dispatch,下面的代码工作正常: protocol VariableType { associatedtype T var value : T { get } } class UserDefaultsVariable<T> : VariableType { let storageKey : String var value : T { get { return U
protocol VariableType {
associatedtype T
var value : T { get }
}
class UserDefaultsVariable<T> : VariableType {
let storageKey : String
var value : T {
get {
return UserDefaults.standard.object(forKey: storageKey) as! T
}
set(value) {
UserDefaults.standard.set(value, forKey: storageKey)
}
}
init( storageKey : String, initialValue : T ) {
self.storageKey = storageKey
// I want dynamic dispatch here so that if T: RawRepresentable then the
// function in the extension is called
self.registerDefaultValue(initialValue: initialValue)
}
func registerDefaultValue( initialValue : T ) {
debugPrint("this is called both times!")
UserDefaults.standard.register(defaults: [storageKey : initialValue])
}
}
当我称之为:
let simpleDefault = UserDefaultsVariable<Int>(storageKey: "simple", initialValue: 0)
let initialValue = simpleDefault.value
enum Direction : Int {
case left = 0
case right = 1
}
let enumedDefault = UserDefaultsVariable<Direction>(storageKey: "enumed", initialValue: .left)
这将很好地编译,并从超类中的初始值设定项调用子类中的registerDefaultValue
我真的很感谢你的帮助。我认为你在概念上遇到的问题是,事实上,这个故事中没有“动态调度”。动态分派是一种涉及多态性的运行时机制,您的代码不包含多态性。泛型完全在编译时解析:将要发生的事情显式地写入代码中 要了解我的意思,只需执行以下操作:将所有
UserDefaultsVariable(…)
更改为UserDefaultsVariable.init(…)
,以给自己一些可以单击的内容,然后启动Control命令单击术语。您将看到我们从何处跳到编译器如何路由每个调用
enumedDefault
显式键入为UserDefaultsVariable
。你就是这样打的。所以我们(皇家编译器“我们”)知道调用什么registerDefaultValue
。没有“派遣”。但是没有(也不可能)为RAW可表示扩展定义任何特殊指定的init
,而self
只是self
在初始值设定项中。因此,初始值设定项不会基于某种运行时测试(泛型参数化类型是否符合RawRepresentable)神奇地调用另一个registerDefaultValue
。我认为您遇到的概念性问题是,事实上,在这个故事中没有“动态调度”。动态分派是一种涉及多态性的运行时机制,您的代码不包含多态性。泛型完全在编译时解析:将要发生的事情显式地写入代码中
要了解我的意思,只需执行以下操作:将所有UserDefaultsVariable(…)
更改为UserDefaultsVariable.init(…)
,以给自己一些可以单击的内容,然后启动Control命令单击术语。您将看到我们从何处跳到编译器如何路由每个调用
enumedDefault
显式键入为UserDefaultsVariable
。你就是这样打的。所以我们(皇家编译器“我们”)知道调用什么registerDefaultValue
。没有“派遣”。但是没有(也不可能)为RAW可表示扩展定义任何特殊指定的init
,而self
只是self
在初始值设定项中。因此,初始值设定项不会基于某种运行时测试(泛型参数化类型是否符合RawRepresentable)神奇地调用另一个registerDefaultValue
。这里是一种可能的方法
这样做的目的是使初始值设定项在扩展中更加方便,从而使泛型专用扩展与默认扩展重叠
测试并使用Xcode 11.4/swift 5.2
class UserDefaultsVariable<T> : VariableType {
let storageKey : String
init(storageKey: String) {
self.storageKey = storageKey
}
var value : T {
get {
return UserDefaults.standard.object(forKey: storageKey) as! T
}
set(value) {
UserDefaults.standard.set(value, forKey: storageKey)
}
}
func registerDefaultValue( initialValue : T ) {
UserDefaults.standard.register(defaults: [storageKey : initialValue])
}
}
extension UserDefaultsVariable {
// this initializer uses default T
convenience init(storageKey : String, initialValue : T) {
self.init(storageKey: storageKey)
self.registerDefaultValue(initialValue: initialValue)
}
}
extension UserDefaultsVariable where T: RawRepresentable {
// this initializer uses specialised T
convenience init(storageKey : String, initialValue : T) {
self.init(storageKey: storageKey)
self.registerDefaultValue(initialValue: initialValue)
}
var value: T {
get {
let rawValue = UserDefaults.standard.object(forKey: storageKey) as! T.RawValue
return T(rawValue: rawValue)!
}
set {
UserDefaults.standard.set(newValue.rawValue, forKey: storageKey)
}
}
func registerDefaultValue( initialValue : T ) {
UserDefaults.standard.register(defaults: [storageKey:initialValue.rawValue])
}
}
class UserDefaultsVariable:VariableType{
让storageKey:字符串
init(storageKey:String){
self.storageKey=storageKey
}
var值:T{
得到{
将UserDefaults.standard.object(forKey:storageKey)返回为!T
}
设置(值){
UserDefaults.standard.set(值,forKey:storageKey)
}
}
func registerDefaultValue(初始值:T){
UserDefaults.standard.register(默认值:[storageKey:initialValue])
}
}
扩展UserDefaultsVariable{
//此初始值设定项使用默认的T
便利初始化(storageKey:String,initialValue:T){
self.init(storageKey:storageKey)
self.registerDefaultValue(initialValue:initialValue)
}
}
扩展UserDefaultsVariable,其中T:RawRepresentable{
//此初始值设定项使用专门的T
便利初始化(storageKey:String,initialValue:T){
self.init(storageKey:storageKey)
self.registerDefaultValue(initialValue:initialValue)
}
var值:T{
得到{
将rawValue=UserDefaults.standard.object(forKey:storageKey)设为!T.rawValue
返回T(原始值:原始值)!
}
设置{
UserDefaults.standard.set(newValue.rawValue,forKey:storageKey)
}
}
func registerDefaultValue(初始值:T){
UserDefaults.standard.register(默认值:[storageKey:initialValue.rawValue])
}
}
这里是可能的方法
这样做的目的是使初始值设定项在扩展中更加方便,从而使泛型专用扩展与默认扩展重叠
测试并使用Xcode 11.4/swift 5.2
class UserDefaultsVariable<T> : VariableType {
let storageKey : String
init(storageKey: String) {
self.storageKey = storageKey
}
var value : T {
get {
return UserDefaults.standard.object(forKey: storageKey) as! T
}
set(value) {
UserDefaults.standard.set(value, forKey: storageKey)
}
}
func registerDefaultValue( initialValue : T ) {
UserDefaults.standard.register(defaults: [storageKey : initialValue])
}
}
extension UserDefaultsVariable {
// this initializer uses default T
convenience init(storageKey : String, initialValue : T) {
self.init(storageKey: storageKey)
self.registerDefaultValue(initialValue: initialValue)
}
}
extension UserDefaultsVariable where T: RawRepresentable {
// this initializer uses specialised T
convenience init(storageKey : String, initialValue : T) {
self.init(storageKey: storageKey)
self.registerDefaultValue(initialValue: initialValue)
}
var value: T {
get {
let rawValue = UserDefaults.standard.object(forKey: storageKey) as! T.RawValue
return T(rawValue: rawValue)!
}
set {
UserDefaults.standard.set(newValue.rawValue, forKey: storageKey)
}
}
func registerDefaultValue( initialValue : T ) {
UserDefaults.standard.register(defaults: [storageKey:initialValue.rawValue])
}
}
class UserDefaultsVariable:VariableType{
让storageKey:字符串
init(storageKey:String){
self.storageKey=storageKey
}
var值:T{
得到{
将UserDefaults.standard.object(forKey:storageKey)返回为!T
}
设置(值){
UserDefaults.standard.set(值,forKey:storageKey)
}
}
func registerDefaultValue(初始值:T){
UserDefaults.standard.register(默认值:[storageKey:initialValue])
}
}
扩展UserDefaultsVariable{
//此初始值设定项使用默认的T
便利初始化(storageKey:String,initialValue:T){
self.init(storageKey:storageKey)
self.registerDefaultValue(initialValue:initialValue)
}
}
扩展UserDefaultsVariable,其中T:RawRepresentable{
//此初始值设定项使用专门的T
便利初始化(storageKey:String,initialValue:T){
self.init(storageKey:storageKey)
self.registerDefaultValue(initialValue:initialValue)
}
var值:T{
得到{
将rawValue=UserDefaults.standard.object(forKey:storageKey)设为!T.rawValue
返回T(原始值:原始值)!
}
设置{
UserDefaults.standard.set(newValue.rawValue,forKey:storageKey)
class RawRepresentableUserDefaultsVariable<T: RawRepresentable> : UserDefaultsVariable<T>{
override var value: T {
get {
let rawValue = UserDefaults.standard.object(forKey: storageKey) as! T.RawValue
return T(rawValue: rawValue)!
}
set {
UserDefaults.standard.set(newValue.rawValue, forKey: storageKey)
}
}
override func registerDefaultValue( initialValue : T ) {
UserDefaults.standard.register(defaults: [storageKey:initialValue.rawValue])
}
}
let enumedDefault = RawRepresentableUserDefaultsVariable<Direction>(storageKey: "enumed", initialValue: .left)
let initialEnumValue = enumedDefault.value
class UserDefaultsVariable<T> : VariableType {
let storageKey : String
init(storageKey: String) {
self.storageKey = storageKey
}
var value : T {
get {
return UserDefaults.standard.object(forKey: storageKey) as! T
}
set(value) {
UserDefaults.standard.set(value, forKey: storageKey)
}
}
func registerDefaultValue( initialValue : T ) {
UserDefaults.standard.register(defaults: [storageKey : initialValue])
}
}
extension UserDefaultsVariable {
// this initializer uses default T
convenience init(storageKey : String, initialValue : T) {
self.init(storageKey: storageKey)
self.registerDefaultValue(initialValue: initialValue)
}
}
extension UserDefaultsVariable where T: RawRepresentable {
// this initializer uses specialised T
convenience init(storageKey : String, initialValue : T) {
self.init(storageKey: storageKey)
self.registerDefaultValue(initialValue: initialValue)
}
var value: T {
get {
let rawValue = UserDefaults.standard.object(forKey: storageKey) as! T.RawValue
return T(rawValue: rawValue)!
}
set {
UserDefaults.standard.set(newValue.rawValue, forKey: storageKey)
}
}
func registerDefaultValue( initialValue : T ) {
UserDefaults.standard.register(defaults: [storageKey:initialValue.rawValue])
}
}