如何用它的超类的实例启动我的子类?
在我的应用我读类型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将缓存的数据链接到原始实例。这样你可以保持你的扩展方法。
有斯威夫特没有办法(和一般的大多数面向对象的语言)创建一个子类的实例时使用一个基类对象的现有实例。
从一般的编程待命点你在这种情况下两个选择:
使用组成:使CustomRectangle包含NativeRectangle和转发,你需要的所有方法吧。
使用地图NativeRectangles链接到的其他信息。在Objective C和Swift中,您可以通过objc_AssociationPolicy轻松获得这样的内部映射。见https://*.com/a/43056053/278842
Btw。从“缓存”一个简单的计算,您将无法看到任何加速,如width * height
。
您创建了自己的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
我不认为这是EKEvents的解决方案,因为它们没有适当的构造函数可用。但对于其他类型,它可能是有用的。我会坚持@Christopher Oezbek的建议 –
@Esben von Buchwald对EKEvents或初始化的工作原理没有太多的了解。但是上面的答案是基本的初始化过程,在swift或其他任何语言中很可能都遵循。事实上,你可以坚持使用Oezbek解决方案。 –
构图通常是我不得不这样做时想到的第一个想法。 – Abizern
谢谢 - 当我不得不做一个包装类和映射属性时,我想......我希望有一个更优雅的解决方案。宽度*高度的简单“缓存”就是这个例子...... –