Weak reference between parent and child classes - ios

Can we communicate between classes like below code instead of using delegate/protocol pattern and notification. I haven't seen any code example like this. But just curious to know why this should work or not work.
class Class1 {
var class2Obj: Class2 = Class2()
init() {
class2Obj.class1Obj = self
}
func class1Method() {
print("Parent")
}
}
class Class2 {
weak var class1Obj: Class1?
func class2Method() {
class1Obj.class1Method()
}
}

What you have here is a delegate pattern. Your delegate property is merely called class1Obj rather than the more customary delegate name. The key issue here is that you're not using a protocol, and as a result these two classes are "tightly coupled," i.e. Class2 is highly dependent upon details of the Class1 implementation. Furthermore, with these two tightly coupled classes, it's not immediately clear which methods of Class1 that Class2 might need. It makes maintenance of Class1 harder because so it's easy to accidentally make a change that breaks behavior in Class2. It also makes it hard to use Class2 in conjunction with some other class other than Class1.
Instead, you'd generally declare a protocol to precisely articulate the nature of the contract between Class2 and other object that might need to use it. The result is that the classes are less tightly coupled, i.e. Class2 needs to know nothing about the other class other than its conformance to the protocol in question. Furthermore, when editing Class1, if you declare it to conform the the protocol, the compiler will warn you when you fail to implement some required method or property.
So, with a negligible amount of work up-front, the protocol makes the code much easier to maintain. It also provides some additional flexibility whereby you may use Class2 in conjunction with something other than Class1 in the future.
Bottom line, protocols can result in code that is easier to maintain and is more flexible, with no hidden assumptions.
If you don't want to use the delegate-protocol pattern, another alternative is to use a closure, where Class1 supplies a block of code that Class2 can call. So you can do something like:
class Class1 {
var class2Obj = Class2()
init() {
class2Obj.handler = { [weak self] in // note `weak` reference which avoids strong reference cycle
self?.class1Method()
}
}
func class1Method() {
print("Parent")
}
}
class Class2 {
var handler: (() -> Void)?
func class2Method() {
handler?()
}
}
While the delegate-protocol pattern is useful when you have a rich interface between the two classes, this closure pattern when you have a very simple interface between the two classes.
Frankly, a more common permutation of the above is where the closure is more directly associated with some particular request that Class1 initiates in Class2. So, you might just make the parameter a closure to the appropriate method in Class2. Furthermore, you're often passing data back, so imagine that we're passing back an optional String:
class Class1 {
var class2Obj = Class2()
func performClass2Method() {
class2Obj.class2Method { string in
guard let string = string else { return }
self.class1Method()
}
}
func class1Method() {
print("Parent")
}
}
class Class2 {
func class2Method(completionHandler: #escaping (String?) -> Void) {
// do something which creates `string`
// when done, call the closure, passing that `string` value back
completionHandler(string)
}
}
These closure patterns a great way to do simple interfaces between objects, but also keeps the two classes very loosely coupled (i.e. Class2 has no dependencies upon Class1), much like using a protocol in the delegate pattern did. But hopefully the above closure examples illustrate a simple alternatives to the rich delegate-protocol pattern.

Related

Static function encapsulation in Swift by passing Protocols.Type better than OO encapsulation and just as testable?

Given that I have a function that does not need to share and store state; should I use a static class/struct/enum to hold the function? I have read in many places that it is a bad design to use static functions to hold code, as static function do not adhere to the SOLID principles and are considered procedural code. Testability seems to be there as I can isolate the parent class with the injected static Enums by injecting mock static enums.
E.g. I can encapsulate and have polymorphism by using protocols for static functions:
Static Protocol Approach
enum StaticEnum: TestProtocol {
static func staticMethod() {
print("hello")
}
}
enum StaticEnum2: TestProtocol {
static func staticMethod() {
print("hello2")
}
}
protocol TestProtocol {
static func staticMethod()
}
class TestClass {
let staticTypes: [TestProtocol.Type]
init (staticTypes: [TestProtocol.Type]) {
self.staticTypes = staticTypes
}
}
class TestFactory {
func makeTestClass() -> TestClass {
return TestClass(staticTypes: [StaticEnum.self, StaticEnum2.self])
}
}
vs
Object Oriented Approach
class InstanceClass: TestProtocol {
func instanceMethod() {
print("hello")
}
}
class InstanceClass2: TestProtocol {
func instanceMethod() {
print("hello2")
}
}
protocol TestProtocol {
func instanceMethod()
}
class TestClass {
let instances: [TestProtocol]
init (instances: [TestProtocol]) {
self.instances = instances
}
}
class TestFactory {
func makeTestClass() -> TestClass {
return TestClass(instances: [InstanceClass(), InstanceClass2()])
}
}
The static version still allows for protocol polymorphism as you can have multiple enums adhere to the static protocols. Furthermore no initialisation is needed after the first dispatch call to create the static function. Is there any drawback in using the Static Protocol approach?
Why static methods can violate SOLID
I have read in many places that it is a bad design to use static functions to hold code, as static function do not adhere to the SOLID principles and are considered procedural code.
I suspect you've read about this in the context of other languages, such as Java, which I'll use as a concrete example for simplicity.
Indeed, this is true for Java. But rather than a hand-wavy quote about why static is the boogeyman, it's good to understand the precise details.
In Java, static methods are truly static. They're really no different than a global function that just happens to be namespaced to a class.
As such, it violated the dependency inversion principle (the "D" in SOLID). Any usage of a static method in Java is a case where the calling code is relying on a concretion (that particular implementation of the method) and not an abstraction (an interface that describes that method), making polymorphism impossible. Essentially there's no way to substitute one implementation for another.
... but not in Swift.
This is just not the case in Swift.
In Swift, when a type conforms to a protocol, instances of that type are guaranteed to meet the protocols requirements for instance methods, properties and subscripts, just like Java.
But as you've discovered, when a Swift type conforms to a protocol, the type itself is guaranteed to meet the protocol requirements for static methods, static properties, static subscripts and initializers.
This goes a step beyond what Java's interfaces can express.
I like to visualize it by thinking of each Swift protocol as acting as if it were (up to) two conventional Java interfaces in one.
When you have:
protocol MyProtocol {
static func myStaticMethod() {}
func myInstanceMethod() {}
}
struct MyImplementation: MyProtocol {
static func myStaticMethod() {}
func myInstanceMethod() {}
}
It behaves as if you had (psuedo-code):
interface MyProtocol_MetaHalf {
static func myStaticMethod() {}
}
interface MyProtocol_InstancedHalf {
func myInstanceMethod() {}
}
struct MyImplementation.Type: MyProtocol_MetaHalf {
static func myStaticMethod() {}
}
struct MyImplementation: MyProtocol_InstancedHalf {
func myInstanceMethod() {}
}
You might recognize this as being eerily similar to the way Java interfaces are often used. You'd often have a pair, interface Foo, and interface FooFactory. I argue that the prevalence of "Factory" classes in Java stems from their interfaces' inability to express static requirements, thus what could have been a static method has to be instead split off into an instance method on a new class.
As you've also seen, Swift's static methods can satisfy protocol requirements and they can be polymorphically called. Example:
protocol MyProtocol {
static func staticMethod()
}
struct Imp1: MyProtocol {
static func staticMethod() { print("Imp1") }
}
struct Imp2: MyProtocol {
static func staticMethod() { print("Imp1") }
}
let someImplementation: MyProtocol.Type = Imp1.self
// A polymorphic call to a static method
someImplementation.staticMethod()
Thus, you can see that the testability issue with Java interfaces doesn't translate to Swift's interfaces. You can easily implement a new mock type that conforms to a protocol with a static requirement, and provide a mock implementation to the static method.
All that is to say: What you proposed is possible (well clearly, you provided a working demonstration). But it begs the question: why would you do it?
Why use metatypes when types will do?
Having a type system that supports both types (which describe the methods of their instances, the objects) and metatypes (which describes the methods of their instances, the types) can be useful for expressing ideas like "I have a widget, and it's paired with a thing that makes widgets, here's how the two go together into one protocol/class/struct."
But what you've done is essentially ... dial up the "meta level" by one. In your example, you use types instead of objects, and metatypes instead of types. But fundamentally, you haven't achieved anything that can't already be expressed more easily/clear using the typical pairing of objects + types.
Here's how I would express what you wrote:
struct Implementation1: TestProtocol {
func instanceMethod() {
print("hello")
}
}
struct Implementation2: TestProtocol {
func instanceMethod() {
print("hello2")
}
}
protocol TestProtocol {
func instanceMethod()
}
class TestClass {
let implementations: [TestProtocol]
init(implementations: [TestProtocol]) {
self.implementations = implementations
}
}
class TestFactory {
func makeTestClass() -> TestClass {
return TestClass(implementations: [Implementation1(), Implementation2()])
}
}
Given that I have a function that does not need to share and store state
They might not need that today, but maybe they will need it in the future. Or maybe not. For now, I just modelled the implementations using empty structs.
This is probably a good time to emphasize there's a difference between "I only need one object of this", vs "I'm adamant I only ever want exactly one object of this".
That might sound silly/obvious, but you'd be surprised how frequently post here asking about how they can be two instances of a singleton :)
If you're totally adamant that you'll never need state, then perhaps you enforce the one-objectness constraint with a singleton:
struct Implementation1: TestProtocol {
public static var shared: Self { Self() }
private init() {}
func instanceMethod() {
print("hello")
}
}

Swift generic class, inheritance and covariance

I'm faced with the problem of using generic class and inheritance.
Brief description of the problem:
I have a base class called BookPageDataSource and two inherited classes (ReadingBookPageDataSource and StarsBookPageDataSource) with different implementations.
Also, I have a generic class BookPageViewController that contains the generic parameter of this data source and two inherited classes (ReadingBookPageViewController and StarsBookPageViewController) from this class.
I need to write a method the return parameter of which is BookPageViewController<DataSource>.
// Data Sources
class BookPageDataSource { }
class ReadingBookPageDataSource: BookPageDataSource { }
class StarsBookPageDataSource: BookPageDataSource { }
// Controllers
class BookPageViewController<DataSource: BookPageDataSource>: UIViewController {
let dataSource: DataSource
init(dataSource: DataSource) {
self.dataSource = dataSource
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
return nil
}
}
final class ReadingBookPageViewController: BookPageViewController<ReadingBookPageDataSource> { }
final class StarsBookPageViewController: BookPageViewController<StarsBookPageDataSource> { }
// Communication
class Pager {
func currentPageController<DataSource>(at index: Int) -> BookPageViewController<DataSource> {
// for example
if index == 0 {
// How to remove the cast from the line below?
return readingPageController() as! BookPageViewController<DataSource>
}
return starsPageController() as! BookPageViewController<DataSource>
}
private func readingPageController() -> ReadingBookPageViewController {
return ReadingBookPageViewController(dataSource: ReadingBookPageDataSource())
}
private func starsPageController() -> StarsBookPageViewController {
return StarsBookPageViewController(dataSource: StarsBookPageDataSource())
}
}
The method currentPageController always crashes, because the DataSource is always equals to BookPageDataSource, not to ReadingBookPageDataSource or StarsBookPageDataSource.
Conceptual Discussion
Your concept for the architecture is flawed and this is leading to your issue.
Simple Generics Example
Here's a very simple example of a generic function, which just returns the value you give it:
func echo <T> (_ value: T) -> T { return value }
Because this function is generic, there is ambiguity about the type that it uses. What is T? Swift is a type-safe language, which means that ultimately there is not allowed to be any ambiguity about type whatsoever. So why is this echo function allowed? The answer is that when I actually use this function somewhere, the ambiguity about the type will be removed. For example:
let myValue = echo(7) // myValue is now of type Int and has the value 7
In the act of using this generic function I have removed the ambiguity by passing it an Int, and therefore the compiler has no uncertainty about the types involved.
Your Function
func currentPageController <DataSource> (at index: Int) -> BookPageViewController<DataSource>
Your function only uses the generic parameter DataSource in the return type, not in the input - how is the compiler supposed figure out what DataSource is?* I assume this is how you imagined using your function:
let pager = Pager()
let controller = pager.currentPageController(at: 0)
But now, what is the type of controller? What can you expect to be able to do with it? It seems that you're hoping that controller will take on the correct type based on the value that you pass in (0), but this is not how it works. The generic parameter is determined based on the type of the input, not the value of the input. You're hoping that passing in 0 will yield one return type, while 1 will yield a different one - but this is forbidden in Swift. Both 0 and 1 are of type Int, and the type is all that can matter.
As is usually the case with Swift, it is not the language/compiler that is preventing you from doing something. It is that you haven't yet logically formulated what is even is that you want, and the compiler is just informing you of the fact that what you've written so far doesn't make sense.
Solutions
Let's move on to giving you a solution though.
UIViewController Functionality
Presumably there is something that you wanted to use controller for. What is it that you actually need? If you just want to push it onto a navigation controller then you don't need it to be a BookPageViewController. You only need it to be a UIViewController to use that functionality, so your function can become this:
func currentPageController (at index: Int) -> UIViewController {
if index == 0 {
return readingPageController()
}
return starsPageController()
}
And you can push the controller that it returns onto a navigation stack.
Custom Functionality (Non-Generic)
If, however, you need to use some functionality which is specific to a BookPageViewController then it depends what it is you want to do. If there is a method on BookPageViewController like this:
func doSomething (input: Int) -> String
which doesn't make use of the generic parameter DataSource then probably you'll want to separate out that function into its own protocol/superclass which isn't generic. For example:
protocol DoesSomething {
func doSomething (input: Int) -> String
}
and then have BookPageViewController conform to it:
extension BookPageViewController: DoesSomething {
func doSomething (input: Int) -> String {
return "put your implementation here"
}
}
Now the return type of your function can be this non-generic protocol:
func currentPageController (at index: Int) -> DoesSomething {
if index == 0 {
return readingPageController()
}
return starsPageController()
}
and you can use it like this:
let pager = Pager()
let controller = pager.currentPageController(at: 0)
let retrievedValue = controller.doSomething(input: 7)
Of course, if the return type is no longer a UIViewController of any sort then you probably want to consider renaming the function and the related variables.
Custom Functionality (Generic)
The other option is that you can't separate out the functionality you need into a non-generic protocol/superclass because this functionality makes use of the generic parameter DataSource. A basic example is:
extension BookPageViewController {
func setDataSource (_ newValue: DataSource) {
self.dataSource = newValue
}
}
So in this case you really do need the return type of your function to be BookPageViewController<DataSource>. What do you do? Well, if what you really want is to use the setDataSource(_:) method defined above then you must have a DataSource object that you plan to pass in as an argument, right? If this is the case then we're making progress. Previously, you only had some Int value which you were passing into your function and the problem was that you couldn't specify your generic return type with that. But if you already have a BookPageDataSource value then it is at least logically possible for you to use this to specialize your
function.
What you say you want, however, is to just use an Int to get the controller at that index, regardless of what the DataSource type is. But if you don't care what the DataSource is of the returned BookPageViewController then how can you expect to set its DataSource to something else using the setDataSource(_:) method?
You see, the problem solves itself. The only reason you would need the return type of your function to be generic is if the subsequent functionality you need to make use of uses that generic type, but if this is the case then the controller you get back can't have just any old DataSource (you just wanted whichever one corresponds to the index you provide) - you need it to have exactly the type of DataSource which you plan to pass in when you use it, otherwise you're giving it the wrong type.
So the ultimate answer to your question is that, in the way that you were conceiving of it, there is no possible use for the function you were trying to construct. What's very cool about the way Swift is architected is that the compiler is actually able to figure out that logical flaw and prevent you from building your code until you've re-conceptualized it.
Footnote:
* It is possible to have a generic function which only uses the generic parameter in the return type and not in the input, but this won't help you here.

Mocking with Swift

Consider the following class named SomeClass written in Swift:
#objc class SomeClass: NSObject
{
var shouldCallBar = false
func foo()
{
if (shouldCallBar == true)
{
bar()
}
}
func bar()
{
}
}
For testing the above class foo() method (and similar scenarios mostly written in Objective-C) I was using OCMock like:
- (void) testFooBarShouldBeCalledWhenShouldCallBarIsTrue
{
SomeClass * someClass = [SomeClass new];
// Create mocks.
id mockSomeClass = OCMPartialMock(someClass);
// Expect.
[[mockSomeClass expect] bar];
// Stub.
someClass.shouldCallBar = YES;
// Run code under test.
[someClass foo];
// Verify.
[mockSomeClass verify];
// Stop mocking.
[mockSomeClass stopMocking];
}
But above test fails with Swift code as OCMock won't works well with Swift.
So I am considering something like entirely in Swift:
class SomeClassTests: XCTestCase
{
class MockSomeClass: SomeClass
{
var isBarCalled = false
override func bar()
{
isBarCalled = true
}
}
func testBarShouldBeCalledWhenTrue()
{
let someClass = MockSomeClass()
someClass.shouldCallBar = true
someClass.foo()
XCTAssertTrue(someClass.isBarCalled == true)
}
}
Note here I am subclassing the original class under test and overriding the bar(). I am not at all touching the foo() implementation.
But the downside is I am using MockSomeClass instance to test foo() of SomeClass. This is something I don't like and not recommended.
Is there any better solution to the problem above?
Notes:
I am not talking about Dependency Injection here. Dependency Injection is entirely different approach.
I face these kind of issues when testing UI code in UIViewController.
I have thought of Protocol based programming but was not able to come up with solution to problem above.
So, you want to test that one method (foo) does or does not call another method (bar). The foo method is the one under test, and the bar method is, in the wider sense, a dependent component.
If the invocation of bar has lasting side effects, you could get away with testing that the side effect is/isn't present, maybe by querying a property or similar. In that case you don't need mocks or similar.
If there are no side effects then you must substitute the dependency. To do so you need a seam at which you place code that can tell the test whether the method has been invoked or not. For that, I can only see the two options that Jon already discussed in the question you refer to.
You either put the two methods into separate classes, in which case the class boundary is the seam. Using a protocol, or just an informal convention, you can then completely replace the class that implements bar. Dependency injection comes in handy here.
If the two methods must stay in the same class then you have to use a subclass boundary as a seam, i.e. you use the fact that you can override methods and implement a test-specific sublass. It's easiest when you can use a mock framework. If that's not an option you have to write the code yourself, much like what you describe in your question.

Protocol Oriented Programming and the Delegate Pattern

A WWDC 2015 session video describes the idea of Protocol-Oriented Programming, and I want to adopt this technique in my future apps. I've been playing around with Swift 2.0 for the last couple of days in order to understand this new approach, and am stuck at trying to make it work with the Delegate Pattern.
I have two protocols that define the basic structure of the interesting part of my project (the example code is nonsense but describes the problem):
1) A delegation protocol that makes accessible some information, similar to UITableViewController's dataSource protocol:
protocol ValueProvider {
var value: Int { get }
}
2) An interface protocol of the entity that does something with the information from above (here's where the idea of a "Protocol-First" approach comes into play):
protocol DataProcessor {
var provider: ValueProvider { get }
func process() -> Int
}
Regarding the actual implementation of the data processor, I can now choose between enums, structs, and classes. There are several different abstraction levels of how I want to process the information, therefore classes appear to fit best (however I don't want to make this an ultimate decision, as it might change in future use cases). I can define a base processor class, on top of which I can build several case-specific processors (not possible with structs and enums):
class BaseDataProcessor: DataProcessor {
let provider: ValueProvider
init(provider: ValueProvider) {
self.provider = provider
}
func process() -> Int {
return provider.value + 100
}
}
class SpecificDataProcessor: BaseDataProcessor {
override func process() -> Int {
return super.process() + 200
}
}
Up to here everything works like a charm. However, in reality the specific data processors are tightly bound to the values that are processed (as opposed to the base processor, for which this is not true), such that I want to integrate the ValueProvider directly into the subclass (for comparison: often, UITableViewControllers are their own dataSource and delegate).
First I thought of adding a protocol extension with a default implementation:
extension DataProcessor where Self: ValueProvider {
var provider: ValueProvider { return self }
}
This would probably work if I did not have the BaseDataProcessor class that I don't want to make value-bound. However, subclasses that inherit from BaseDataProcessor and adopt ValueProvider seem to override that implementation internally, so this is not an option.
I continued experimenting and ended up with this:
class BaseDataProcessor: DataProcessor {
// Yes, that's ugly, but I need this 'var' construct so I can override it later
private var _provider: ValueProvider!
var provider: ValueProvider { return _provider }
func process() -> Int {
return provider.value + 10
}
}
class SpecificDataProcessor: BaseDataProcessor, ValueProvider {
let value = 1234
override var provider: ValueProvider { return self }
override func process() -> Int {
return super.process() + 100
}
}
Which compiles and at first glance appears to do what I want. However, this is not a solution as it produces a reference cycle, which can be seen in a Swift playground:
weak var p: SpecificDataProcessor!
autoreleasepool {
p = SpecificDataProcessor()
p.process()
}
p // <-- not nil, hence reference cycle!
Another option might be to add class constraints to the protocol definitions. However, this would break the POP approach as I understand it.
Concluding, I think my question boils down to the following: How do you make Protocol Oriented Programming and the Delegate Pattern work together without restricting yourself to class constraints during protocol design?
It turns out that using autoreleasepool in Playgrounds is not suited to proof reference cycles. In fact, there is no reference cycle in the code, as can be seen when the code is run as a CommandLine app. The question still stands whether this is the best approach. It works but looks slightly hacky.
Also, I'm not too happy with the initialization of BaseDataProcessors and SpecificDataProcessors. BaseDataProcessors should not know any implementation detail of the sub classes w.r.t. valueProvider, and subclasses should be discreet about themselves being the valueProvider.
For now, I have solved the initialization problem as follows:
class BaseDataProcessor: DataProcessor {
private var provider_: ValueProvider! // Not great but necessary for the 'var' construct
var provider: ValueProvider { return provider_ }
init(provider: ValueProvider!) {
provider_ = provider
}
func process() -> Int {
return provider.value + 10
}
}
class SpecificDataProcessor: BaseDataProcessor, ValueProvider {
override var provider: ValueProvider { return self } // provider_ is not needed any longer
// Hide the init method that takes a ValueProvider
private init(_: ValueProvider!) {
super.init(provider: nil)
}
// Provide a clean init method
init() {
super.init(provider: nil)
// I cannot set provider_ = self, because provider_ is strong. Can't make it weak either
// because in BaseDataProcessor it's not clear whether it is of reference or value type
}
let value = 1234
}
If you have a better idea, please let me know :)

Override var conforming to a protocol with a var conforming to a child of the overridden var protocol

This is my inheritance structure
Protocols
protocol BaseProtocol {
}
protocol ChildProtocol: BaseProtocol {
}
Classes
class BaseClass: NSObject {
var myVar: BaseProtocol!
}
class ChildClass: BaseClass {
override var myVar: ChildProtocol!
}
I'm receiving a compiler error:
Property 'myVar' with type 'ChildProtocol!' cannot override a property with type 'BaseProtocol!'
What is the best approach to achieve this?
UPDATE
I updated the question trying to implement the solution with generics but it does not work :( This is my code (now the real one, without examples)
Protocols
protocol TPLPileInteractorOutput {
}
protocol TPLAddInteractorOutput: TPLPileInteractorOutput {
func errorReceived(error: String)
}
Classes
class TPLPileInteractor<T: TPLPileInteractorOutput>: NSObject, TPLPileInteractorInput {
var output: T!
}
And my children
class TPLAddInteractor<T: TPLAddInteractorOutput>: TPLPileInteractor<TPLPileInteractorOutput>, TPLAddInteractorInput {
}
Well, inside my TPLAddInteractor I can't access self.output, it throws a compiler error, for example
'TPLPileInteractorOutput' does not have a member named 'errorReceived'
Besides that, when I create the instance of TPLAddInteractor
let addInteractor: TPLAddInteractor<TPLAddInteractorOutput> = TPLAddInteractor()
I receive this other error
Generic parameter 'T' cannot be bound to non-#objc protocol type 'TPLAddInteractorOutput'
Any thoughts?
#tskulbru is correct: it can't be done, and this has nothing to do with your protocols. Consider the example below, which also fails…this time with Cannot override with a stored property 'myVar':
class Foo {
}
class Goo: Foo {
}
class BaseClass: NSObject {
var myVar: Foo!
}
class ChildClass: BaseClass {
override var myVar: Foo!
}
To understand why, let's reexamine the docs:
Overriding Properties
You can override an inherited instance or class property to provide
your own custom getter and setter for that property, or to add
property observers to enable the overriding property to observe when
the underlying property value changes.
The implication is that if you are going to override a property, you must write your own getter/setter, or else you must add property observers. Simply replacing one variable type with another is not allowed.
Now for some rampant speculation: why is this the case? Well, consider on the one hand that Swift is intended to be optimized for speed. Having to do runtime type checks in order to determine whether your var is in fact a Foo or a Bar slows things down. Then consider that the language designers likely have a preference for composition over inheritance. If both of these are true, it's not surprising that you cannot override a property's type.
All that said, if you needed to get an equivalent behavior, #tskulbru's solution looks quite elegant, assuming you can get it to compile. :)
I don't think you can do that with protocols
The way i would solve the problem you are having is with the use of generics. This means that you essentially have the classes like this (Updated to a working example).
Protocols
protocol BaseProtocol {
func didSomething()
}
protocol ChildProtocol: BaseProtocol {
func didSomethingElse()
}
Classes
class BaseClass<T: BaseProtocol> {
var myProtocol: T?
func doCallBack() {
myProtocol?.didSomething()
}
}
class ChildClass<T: ChildProtocol> : BaseClass<T> {
override func doCallBack() {
super.doCallBack()
myProtocol?.didSomethingElse()
}
}
Implementation/Example use
class DoesSomethingClass : ChildProtocol {
func doSomething() {
var s = ChildClass<DoesSomethingClass>()
s.myProtocol = self
s.doCallBack()
}
func didSomething() {
println("doSomething()")
}
func didSomethingElse() {
println("doSomethingElse()")
}
}
let foo = DoesSomethingClass()
foo.doSomething()
Remember, you need a class which actually implements the protocol, and its THAT class you actually define as the generic type to the BaseClass/ChildClass. Since the code expects the type to be a type which conforms to the protocol.
There are two ways you can go with your code, depending what you want to achieve with your code (you didn't tell us).
The simple case: you just want to be able to assign an object that confirms to ChildProtocol to myVar.
Solution: don't override myVar. Just use it in ChildClass. You can do this by design of the language Swift. It is one of the basics of object oriented languages.
Second case: you not only want to enable assigning instances of ChildProtocol, you also want to disable to be able to assign instances of BaseProtocol.
If you want to do this, use the Generics solution, provided here in the answers section.
If you are unsure, the simple case is correct for you.
Gerd

Resources