Reputation: 2154
I have an abstract class in my mind and I can't implement its several features in swift, so I use C++ to deliver my thoughts:
template <class T>
class Swapping {
public:
void swap() { _foregroundIndex = backgroundIndex() }
virtual void cleanup() = 0;
T* foreground() { return _buffer[foregroundIndex()]; }
T* background() { return _buffer[backgroundIndex()]; }
void setForeground(T* foreground) { _buffer[foregroundIndex()] = foreground; }
void setBackground(T* background) { _buffer[backgroundIndex()] = background; }
private:
short foregroundIndex() { return _foregroundIndex; }
short backgroundIndex() { return _foregroundIndex ^ 1; }
short _foregroundIndex = 0;
T* _buffer[2] = {NULL, NULL};
}
The main contradiction is that
cleanup()
requires all subclasses to implement it explicitly (can achieve in swift with protocol
)_foregroundIndex
has an initial value (cannot achieve using protocol
)_foregroundIndex
is restricted to be private
( cannot achieve using protocol
)On the other hand, if I use a class
instead of protocol
, then I can't guarantee cleanup()
method is overriden.
One may suggest that put the virtual method in a protocol
and the instance variable in a class
. That may work but is not a obsession-satisfying one.
P.S. Objective-C is not Swift. Any objc_runtime
related workaround is not preferred.
Upvotes: 3
Views: 73
Reputation: 14895
There’s an obvious solution, which I have seen often but will certainly not satisfy you is:
func cleanup() {
fatalError("You must override cleanup()")
}
Then you could try using extension
s to extend the protocol with default implementations, but extensions don’t allow stored properties and so you would most likely need some external objects or other magic you certainly also dislike.
As I noted above in the comments, you might need to rethink your design. I don’t know what you really intend to do, but maybe something like this would work out for you:
class Swapper<T> {
private var foregroundIndex = 0
private var backgroundIndex: Int {
return foregroundIndex ^ 1
}
private var buffer: [T?] = [nil, nil]
private let cleanupHandler: () -> ()
init(cleanupHandler: @escaping () -> ()) {
self.cleanupHandler = cleanupHandler
}
func cleanup() {
cleanupHandler()
}
var foreground: T? {
get {
return buffer[foregroundIndex]
}
set {
buffer[foregroundIndex] = newValue
}
}
var background: T? {
get {
return buffer[backgroundIndex]
}
set {
buffer[backgroundIndex] = newValue
}
}
func swap() {
foregroundIndex = backgroundIndex
}
}
This makes more sense to me as this allows any types to be swapped with any clean up handler, without having to subclass the class every time.
Upvotes: 2