如何用它的超类的实例启动我的子类?

问题描述:

在我的应用我读类型EKEvent的日历事件,我已经做了很多计算瓦尔的扩展,这样我就可以轻松搞定的持续时间,工时数等,在日历中的每个事件。但在大规模情况下,性能很差 - 所以我想使用懒惰变量来缓存所有额外的数据。如何用它的超类的实例启动我的子类?

因此,我想创建EKEvent的一个子类 - 称为CustomEvent,它添加了懒惰的变量,但是我的问题是EKEventStore总是返回EKEvents,我需要将它转换为我的CustomEvent子类的实例,按顺序要能够访问懒瓦尔等

一个简单的类型转换是不够的,我试过在一个操场上,看看有什么可以工作,但什么也没得到有用。我需要一个CustomRectangle的特殊构造函数,它可以从NativeRectangle初始化一个CustomRectangle。另一种解决方案是使持有原来的对象作为属性的包装类,但是这不会是我最喜欢的解决方案,因为我接下来要映射所有的方法和属性

class NativeRectangle: NSObject { 
    var width: Int 
    var height: Int 

    init(width: Int, height: Int) { 
     self.width = width 
     self.height = height 
     super.init() 
    } 
} 

class CustomRectangle: NativeRectangle { 
    var area: Int { return width * height} 
} 

let rect = NativeRectangle(width: 100, height: 20) 

let customRect = CustomRectangle(rect) // This fails, i need a constructor 

print(customRect.area) 

如果你已经在Objective-C的土地工作,有包装的原生类,并自动将所有(除加)消息的选项:

- (NSMethodSignature*) methodSignatureForSelector: (SEL) selector 
{ 
    NSMethodSignature *ours = [super methodSignatureForSelector:selector]; 
    return ours ?: [wrappedObject methodSignatureForSelector:selector]; 
} 

我不记得,如果这是需要的转发一切工作,但它应该非常接近。另外,我不知道如何做到这一点与斯威夫特玩,所以我想我们可以考虑从这个Objective-C的天一个有趣的琐事,并寻找一个更好的解决方案...


第二个,也想到的稍微黑客的选项是使用associated objects feature将缓存的数据链接到原始实例。这样你可以保持你的扩展方法。

有斯威夫特没有办法(和一般的大多数面向对象的语言)创建一个子类的实例时使用一个基类对象的现有实例。

从一般的编程待命点你在这种情况下两个选择:

  1. 使用组成:使CustomRectangle包含NativeRectangle和转发,你需要的所有方法吧。

  2. 使用地图NativeRectangles链接到的其他信息。在Objective C和Swift中,您可以通过objc_AssociationPolicy轻松获得这样的内部映射。见https://*.com/a/43056053/278842

Btw。从“缓存”一个简单的计算,您将无法看到任何加速,如width * height

+0

构图通常是我不得不这样做时想到的第一个想法。 – Abizern

+0

谢谢 - 当我不得不做一个包装类和映射属性时,我想......我希望有一个更优雅的解决方案。宽度*高度的简单“缓存”就是这个例子...... –

您创建了自己的CustomRectangle(object: rect),因此swift不会再提供默认的init()。你明确需要打电话给你自己的一个持有你的财产,并致电super.init(),因为你的课程也从超类继承。 -

class NativeRectangle: NSObject { 
    var width: Int 
    var height: Int 

    // Super class custom init() 
    init(width: Int, height: Int) { 
     self.width = width 
     self.height = height 
     super.init() 
    } 
} 

class CustomRectangle: NativeRectangle { 

    // computed property area 
    var area: Int { return width * height} 

    // Sub class Custom Init 
    init(object:NativeRectangle) { 
     // call to super to check proper initialization 
     super.init(width: object.width, height: object.height) 
    } 
} 

let rect = NativeRectangle(width: 100, height: 20) 

let customRect = CustomRectangle(object: rect) 

print(customRect.area) //2000 
+0

我不认为这是EKEvents的解决方案,因为它们没有适当的构造函数可用。但对于其他类型,它可能是有用的。我会坚持@Christopher Oezbek的建议 –

+0

@Esben von Buchwald对EKEvents或初始化的工作原理没有太多的了解。但是上面的答案是基本的初始化过程,在swift或其他任何语言中很可能都遵循。事实上,你可以坚持使用Oezbek解决方案。 –