Inheriting initializer from generic class - ios

I've seen some discussions about this problem, but have not read a satisfactory explanation. Can anybody tell me why this does not work?
class Parent<T> {
var data:T
init(data:T) {
self.data = data
}
}
class Child : Parent<Int> {}
let c = Child(data: 4)
The last line gives the error:
'Child' cannot be constructed because it has no accessible initializers
Do I really need to implement the initializer just to call super?
Edit:
To give a bit of context, the real code looks closer to the below. I have an Action class which uses generics, because I have another bit of code which can chain actions together and I want to use Swift's type safety to ensure that actions can be chained. Then I have a bunch of subclasses classes (e.g. CustomAction). I am looking for a way to avoid overriding the init method in each of the subclasses. Or alternatively, I want to understand why that's not possible.
class Action<Input, Output> {
var cachedOutput:Output?
init(cachedOutput:Output?) {
self.cachedOutput = cachedOutput
}
}
protocol CustomInput {}
protocol CustomOutput {}
class CustomAction : Action<CustomInput, CustomOutput> {
}

yes, you really need to override init method ..
class Parent<T> {
var data:T
init(data:T) {
self.data = data
}
}
class Child<T> : Parent<T> {
override init(data: T) {
super.init(data: data)
}
}
let c = Child(data: 4) // Child<Int>
let c2 = Child(data: "alfa") // Child<String>
what are the errors ...
// what is the type T ? it is undeclared!
class Child2: Parent2<T> {}
// how to specialize non-generic type Parent ? how to create it?
// i need an initializer in class Child3 ... Hm ...
class Child3: Parent<Int> {}
// cannot specialize non-generic type 'Parent'
class Child3: Parent<Int> {
override init(data: Int) {
super.init(data: data)
}
}
// So, Child3 must be of the same specialized type as Parent!!
that is terrible, isn't it? so look at my final example !
class Parent<T> {
var data:T
init(data:T) {
self.data = data
}
}
class Child<Double> : Parent<String> {
init(data: Double) {
super.init(data: "\(data)")
}
}
let c = Child(data: 4) // Child<Int> !!!!!
let d = Child(data: true) // Child<Bool> !!!
in your case it works like
class Parent<T> {
var data:T
init(data:T) {
self.data = data
}
}
class Child: Parent<String> {
init(data: Double) {
super.init(data: "\(data)")
}
}
let c = Child(data: 4)
print(c.dynamicType) // Child :-)

This now works in Swift 3. My original example now compiles. There is no mention of this in the Swift 3 Language changes, so I can only assume that this was a bug.

Related

Swinject: How to use delegate pattern with interface segregation (class vs interface)?

I'm working my way into the injection dependency issue. Now the question arises how to use the interface segregation principle in the case of the delegate pattern? I am using the Swinject framework for dependency injection. How can I solve this?
class Client {
private var interface: ParentInterface
...
func execute() {
interface = globalContainer.resolve(ParentInterface.self)
interface?.parentMethod()
}
}
protocol ParentInterface {
func parentMethod()
}
class Parent: ParentInterface, ParentDelegate {
// Dependency
private var child: Child? // 🚨 I WANT TO USE AN PROTOCOL HERE, NOT THE CLASS
init(childReference: Child) {
self.child = childReference
self.child?.delegate = self // 🚨 But if I use the protocol I cant access the delegate property
}
public func parentMethod() {
let result = calcSomething()
// Access child class interface method
child?.childMethod(result)
}
...
}
The child class, nothing unusual so far.
protocol ParentDelegate: class {
func delagteMethod(value: Double)
}
protocol ChildInterface {
func childMethod(_ result: Double)
}
class Child: ChildInterface {
weak var delegate: ParentDelegate?
...
private func delagteMethod() {
delegate?.delagteMethod(value: someValue)
}
}
But to inject the dependencies properly I need a protocol and not a direct class reference, right? Like this:
// 🚨 Would like to
container.register(ParentInterface.self) { r in
Parent(childInterface: r.resolve(ChildInterface.self)!)
}
// 🚨 Only way I get it working without interface
container.register(ParentDelegate.self) { r in
Parent(childClass: Child())
}
container.register(ChildInterface.self) { _ in Child() }
.initCompleted { r, c in
let child = c as! Child
child.delegate = r.resolve(ParentDelegate.self)
}
In short, I'm going around in circles. If I use an interface for the child class I can't access the delegate property, if I use a class reference I can't reasonably to mock/stub the interface methods.
What am I missing? Thanks a lot in advance!
I would recommend removing self.child?.delegate = self from the Parent constructor for two reasons:
Shouldn't the DI framework be responsible for wiring all the dependencies?
In Swinject specifically, this may lead to incorrect dependencies, see the remark in docs
Pattern that I tend to use is more or less what you came up with:
class Parent: ParentInterface, ParentDelegate {
init(child: ChilInterface) { self.child = child }
}
class Child: ChildInterface {
weak var parent: ParentDelegate?
}
container.register(ParentInterface.self) { Parent(child: $0.resolve(ChildInterface.self)!) }
.implements(ParentDelegate.self)
container.register(ChildInterface.self) { _ in Child() }
.initCompleted { ($1 as! Child).delegate = $0.resolve(ParentDelegate.self) }
Additionally, if you wanted to get rid of force casting, you could do something like:
container.register(Child.self) { _ in Child() }
.implements(ChildInterface.self)
.initCompleted { $1.delegate = $0.resolve(ParentDelegate.self) }

Check if object inherits from generic class or arbitrary set of classes in swift

I have a mutable set of classes - or better class types - and want to check that a random object - directly or indirectly - inherits any of these classes.
I've written a small Playground Test for direct inheritance check using === and indirect check using is or as?:
import Foundation
protocol Product {init()}
class LowGradeProduct: Product {required init() {}}
class HighGradeProduct: Product {required init() {}}
class A: LowGradeProduct {}
class B: HighGradeProduct {}
class ExtraFancyB: B {}
class C: HighGradeProduct {}
class RandomClass {}
class SnobjectChecker {
var allowedClass: [HighGradeProduct.Type] = []
func addCls( cls: HighGradeProduct.Type ) {
allowedClass.append(cls)
}
func checkCls( obj: AnyObject ) -> Bool {
for allowedCls in allowedClass {
/* 1. check object class equality, works */
if type(of: obj) as AnyClass === allowedCls as AnyClass {
return true
}
/* 2. check object class heritance via upcast: not working */
if let _ = obj as? allowedCls {
return true
}
/* 3. check object class heritance via is: not working */
if obj is allowedCls {
return true
}
}
return false
}
}
let fac = SnobjectChecker.init()
fac.addCls(cls: B.self)
for cls in [A.self, B.self, C.self, ExtraFancyB.self] as! [Product.Type] {
print("object of \(cls) is allowed: \(fac.checkCls(obj: cls.init() as AnyObject))")
}
print("object of \(RandomClass.self) is allowed: \(fac.checkCls(obj: RandomClass.init() as AnyObject))")
The check of class equality works but it misses indirect inheritance like ExtraFancyB.
Neither is nor the upcast as? do work, it seems they both only allow static Types since the compiler complains about a missing type allowedCls.
Is there another way to check if an object inherits from a random set of classes to accomplish this with swift 2.3/3+ and if possible without some hacks like classname comparison?

Can we access overridden class function from the base class in swift?

Am stuck in a situation where I have a let variable declared & initialized in base class. I would need to pass a different enum in one of my other classes extending this base class.
So, I tried creating a class function in base class so that I can override and return a different enum type. But is there any way that I can access the extended class from base class ?
Created a sample code below to help explain:
class A {
var string: String {
get {
// Is it possible to refer to the class type dynamically here ?
// So that it would call B's printMessage
return A.printMessage("Hello")
}
}
class func printMessage(message: String) -> String {
return "You shall not pass !"
}
}
class B: A {
override class func printMessage(message:String) -> String {
return message + "World !"
}
}
let obj = B()
print(obj.string)
make it like this:
var string: String {
get {
// Is it possible to refer to the class type dynamically here ?
// So that it would call B's printMessage
return self.dynamicType.printMessage("Hello")
}
}

Swift doesn't recognize Type variables

In my project I am having an issue with Swift, that it doesn't recognize variables containing protocol types. This means I can't use a variable that stores a type, to check if the type of an instance matches it.
I attached problematic part of the code with some brief context.
Is this some kind of bug or am I overseeing something really badly?
Using XCode 7.3, Swift 2.2
//Context of Issue BEGIN
class TaskValueObject {
//ManyData, VeryComplexity, SoBig, wow..
}
typealias TaskListSorterBlock = (TaskValueObject, TaskValueObject) -> Bool
protocol TaskListSorter : class {
init()
var localizedTitle : String { get }
var sorterBlock : TaskListSorterBlock { get }
}
class PriorityTaskListSorter : TaskListSorter {
// ... Implementation ...
}
// Many other TaskListSorter implementation classes ...
//Context of Issue END
class TaskListContainer {
weak var currentSorter : TaskListSorter?
var sorters : [TaskListSorter]
init() {
self.sorters = [ PriorityTaskListSorter(), /* ... Instances created for <TaskListSorter> implementing class ... */ ]
loadDefaultSorter()
}
static var defaultSorterType : TaskListSorter.Type = PriorityTaskListSorter.self
private func loadDefaultSorter() {
let defaultSorterType = TaskListContainer.defaultSorterType
for sorter in self.sorters {
if sorter is defaultSorterType {
// ^ ERROR HERE : defaultSorterType is not a 'type'
self.currentSorter = sorter
}
}
}
}
Update 1: I get the same error if I replace the problematic line with the following:
if let defaultSorter = sorter as? defaultSorterType {
Update 2: Replacing the problematic line with the one below, makes the code work. However I am using here the 'dynamicType' which is not offered by code completion (must be a reason for that...). Also the question remains, why the first 2 attempts didn't work?
if sorter.dynamicType == defaultSorterType {

Initialiser Inheritance confusion

I am trying to build some mocking infrastructure, I want to be able to return a stubbed value and count the times the value was accessed. I have something simple like this:
class BasicMock<T> {
var callsCount = 0
private let backing: T
var result: T {
callsCount++
return backing
}
init(result: T) {
self.backing = result
}
}
class MockTimeDefinitionSerialiser: BasicMock<[String: [AnyObject]]>, TimeDefinitionSerialiserProtocol {
func serialiseTravelTime(travelTime: JSSTravelTime) -> [String: AnyObject] {
return result
}
}
However trying to build it:
let mockTimeDefinitionSerialiser = MockTimeDefinitionSerialiser(result: ["": ""])
Emits the error 'MockTimeDefinitionSerialiser' cannot be constructed because it has no accessible initialisers
My interpretation of the Swift docs is that I should automatically inherit the initialiser as I have set all stored properties.
What am I doing wrong?
Please remove any unnecessary code when asking a question. I was able to reduce your problem to this:
class Base<T> {
init(t: T) {}
}
class Sub: Base<Int> {}
Sub(t: 0) // error: 'Sub' cannot be constructed because it has no accessible initialisers
It seems like even though you specified the T in the subclass, the compiler cannot infer what the initialiser uses for T. I couldn't find a way to get the initialiser to be inherited, you'd have to use a workaround:
class Sub: Base<Int> {
override init(t: Int) {
super.init(t: t)
}
}

Resources