swift protocol with associated type - swift

how can I correct errors?!
domain module, contains all abstracts
//MARK: - Domain
protocol TypeB {
associatedtype P
func makeP() -> P
init()
}
protocol TypeA {
associatedtype P
associatedtype B: TypeB
func makeP() -> P
init(objB: B)
}
protocol FirstTargetFabricType {
func makeB<B: TypeB>() -> B where B.P == Int
}
protocol SecondTargetFabricType {
func makeA<B, A: TypeA>(objcB: B) -> A where A.B == B, A.P == B.P, B.P == Int
}
the first module, for example the module for working with the network
//MARK: - First Target
class ClassB: TypeB {
required init() { }
func makeP() -> Double { return 10 }
}
// error: Cannot convert return expression of type 'ClassB' to return type 'B'
class FirstTargetFabric: FirstTargetFabricType {
func makeB<B: TypeB>() -> B where B.P == Int {
return ClassB()
}
}
the second module, for example the module for working with the storage
//MARK: - SecondTarget
class ClassA<B: TypeB>: TypeA {
let objB: B
required init(objB: B) {
self.objB = objB
}
func makeP() -> B.P { return objB.makeP() }
}
class SecondTargetFabric: SecondTargetFabricType {
func makeA<B, A: TypeA>(objcB: B) -> A where B == A.B, B.P == A.P, B.P == Int {
return A(objB: objcB)
}
}
application target
//MARK: - app
let firstFabric: FirstTargetFabricType = FirstTargetFabric()
let secondFabric: SecondTargetFabricType = SecondTargetFabric()
/// error: Generic parameter 'A' could not be inferred
let res = secondFabric.makeA(objcB: firstFabric.makeB())
I'm trying to make a service loader for pagination. I just want to pass in the class initializer an entity that will go to the network

how good would that approach be?
//MARK: - Domain
open class TypeB<T: Decodable> {
open func makeP() -> T {
fatalError("Required function have not been implemented")
}
}
open class TypeA<T: Decodable> {
open func makeP() -> T {
fatalError("Required function have not been implemented")
}
}
public protocol FirstTargetFabricType {
func makeInt() -> TypeB<Int>
func makeDouble() -> TypeB<Double>
}
public protocol SecondTargetFabricType {
func makeInt(objInt: TypeB<Int>) -> TypeA<Int>
func makeDouble(objDouble: TypeB<Double>) -> TypeA<Double>
}
//MARK: - First Target
internal class ClassB: TypeB<Int> {
override func makeP() -> Int { return 10 }
}
internal class ClassBB: TypeB<Double> {
override func makeP() -> Double { return 20 }
}
public class FirstTargetFabric: FirstTargetFabricType {
public func makeInt() -> TypeB<Int> { ClassB() }
public func makeDouble() -> TypeB<Double> { ClassBB() }
}
//MARK: - SecondTarget
internal class ClassA: TypeA<Int> {
let objB: TypeB<Int>
init(objB: TypeB<Int>) {
self.objB = objB
}
override func makeP() -> Int {
objB.makeP()
}
}
internal class ClassAA: TypeA<Double> {
let objB: TypeB<Double>
init(objB: TypeB<Double>) {
self.objB = objB
}
override func makeP() -> Double {
objB.makeP()
}
}
public class SecondTargetFabric: SecondTargetFabricType {
public func makeInt(objInt: TypeB<Int>) -> TypeA<Int> { ClassA(objB: objInt) }
public func makeDouble(objDouble: TypeB<Double>) -> TypeA<Double> { ClassAA(objB: objDouble) }
}
//MARK: - app
let first = FirstTargetFabric()
let second = SecondTargetFabric()
let objInt = first.makeInt()
let objDouble = first.makeDouble()
print(second.makeInt(objInt: objInt).makeP())
print(second.makeDouble(objDouble: objDouble).makeP())

This is the proper way of doing it with protocols, but that might become very complicated if you keep on going with associated protocols.
In method makeAa: you are trying to return TypeA as type A, and not all TypeA are A, so you have to return A instead
protocol TypeA {
associatedtype P
associatedtype B: TypeB
func makeP() -> P
init(objB: B)
}
protocol TypeB {
associatedtype P
func makeP() -> P
}
class ClassB: TypeB {
func makeP() -> Int { return 10 }
}
class ClassA<B: TypeB>: TypeA {
let objB: B
required init(objB: B) {
self.objB = objB
}
func makeP() -> B.P {
return objB.makeP()
}
}
//**Cannot convert return expression of type 'ClassA<B>' to return type 'A'**
func makeAa<B, A: TypeA>(objB: B) -> A where B.P == Int, A.P == B.P, A.B == B {
return A(objB: objB)
}
//**Generic parameter 'A' could not be inferred**
let res: ClassA = makeAa(objB: ClassB())

For the update:
Again, you have to return type B, not all ClassB are B()
// error: Cannot convert return expression of type 'ClassB' to return type 'B'
class FirstTargetFabric: FirstTargetFabricType {
func makeB<B: TypeB>() -> B where B.P == Int {
return B()
}
}
Here you have to specify generic class B that you want to create (ClassB)
/// error: Generic parameter 'A' could not be inferred
let b: ClassB = firstFabric.makeB()
let res: ClassA = secondFabric.makeA(objcB: b)
And ClassB should return the same (Int) as ClassA to combine them
//MARK: - First Target
class ClassB: TypeB {
required init() { }
func makeP() -> Int { return 10 }
}

Related

How do I using Generic as parameter and return specific object without casting?

Does function can return specific object, when I input a specific class.
My problem:
I don't know how to return a object. take a look following code and thanks
class MyViewControler {
}
class MySplitViewController: NSSplitViewControler {
override func viewDidLoad() {
/*
* get specific object
*/
let vc = viewController(for: MyViewControler.self)
}
}
extension NSSplitViewController {
public func viewController<T>(for anClass: T) -> T.object {
guard let tClass = anClass as? AnyClass else { return nil }
var vc: NSViewController?
if let idx = self.splitViewItems.index(where: { $0.viewController.classForCoder == tClass} ) {
vc = self.splitViewItems[idx].viewController
}
}
/*
* I don't know how to return a specific object
*/
return vc
}
The signature of a method taking a type and returning an
(optional) instance of that type would be:
public func viewController<T>(for aClass: T.Type) -> T?
or, if you want to restrict it to subclasses of NSViewController:
public func viewController<T: NSViewController>(for aClass: T.Type) -> T?
The implementation can be simplified with optional binding:
extension NSSplitViewController {
public func viewController<T: NSViewController>(for aClass: T.Type) -> T? {
for item in self.splitViewItems {
if let vc = item.viewController as? T {
return vc
}
}
return nil
}
}
Or as a "one-liner":
extension NSSplitViewController {
public func viewController<T: NSViewController>(for aClass: T.Type) -> T? {
return self.splitViewItems.lazy.flatMap { $0.viewController as? T }.first
}
}

Swift Protocol Function: returning the same type of conforming class

I want to know if something java-like (or c++) can be done in Swift:
I have a protocol:
protocol Prot1 {
func returnMyself() -> Prot1
}
And a class conforms the protocol Prot1.
Can I force the return type of the function returnMyself() to be the same type of the class like below?
class MyClass: Prot1 {
public func returnMyself() -> MyClass {
return self
}
}
Is it possible?
Just use Self into your protocol
protocol Prot1 {
func returnMyself() -> Prot1
}
Here's an example
protocol Animal {
func mySelf() -> Self
}
class Feline: Animal {
func mySelf() -> Self {
return self
}
}
class Cat: Feline { }
Feline().mySelf() // Feline
Cat().mySelf() // Cat
About protocol extensions
You can also use Self inside a protocol extension like this
protocol Animal {}
extension Animal {
func mySelf() -> Self {
return self
}
}
Now a class just need to conform to Animal like this
class Feline: Animal { }
class Cat: Feline { }
class Dog: Animal {}
and automatically gets the method
Feline().mySelf() // Feline
Cat().mySelf() // Cat
Dog().mySelf() // Dog
Update
protocol ReadableInterval { }
class Interval: ReadableInterval { }
protocol ReadableEvent {
associatedtype IntervalType: ReadableInterval
func getInterval() -> IntervalType
}
class Event: ReadableEvent {
typealias IntervalType = Interval
func getInterval() -> Interval {
return Interval()
}
}
protocol Prot1
{
associatedtype T
func returnMyself() -> T
}
class MyClass : Prot1
{
typealias T = MyClass
func returnMyself() -> T
{
return self
}
}

Swift Inheritance: Super's Super

Supposing to have this three classes with this simply hierarchy:
class A {
func foo() {
print("A")
}
}
class B: A {
override func foo() {
super.foo()
print("B")
}
}
class C: B {
override func foo() {
// *******
print("C")
}
}
In class C, in overrided method foo I want to call a method foo: is it possible?
In C++ this can be achieved with C->A::foo(), but how do I do this in Swift?
super.foo() should be sufficient, since B prints "B" and calls super to print "A".
class C: B {
override func foo() {
super.foo()
print("C")
}
}
let c = C()
c.foo()
Output:
A
B
C
If you want to intentionally expose A's foo() from B, you need to create a new accessor:
class B: A {
override func foo() {
super.foo()
print("B")
}
func exposeFoo() {
super.foo()
}
}
class C: B {
override func foo() {
super.exposeFoo()
print("C")
}
}
Or, use NSObject and the power of the Objective-C runtime:
class A: NSObject { // make sure your base class inherits from NSObject
func foo() {
print("A")
}
}
// ...
class C: B {
override func foo() {
guard let superSuper = self.superclass?.superclass() else {
return; // no super super
}
let fooImp = class_getMethodImplementation(superSuper, "foo")
typealias MyCFunction = #convention(c) (AnyObject, Selector) -> Void
let curriedImplementation = unsafeBitCast(fooImp, MyCFunction.self)
curriedImplementation(self, selector) // prints A
}
}

How to specify that type is class or protocol

import Foundation
#objc public protocol ObjcProtocol {
}
It shows the following error:
Inheritance from non-protocol, non-class type 'A'
public func someFunc(a: A.Type, b: B) -> Bool {
return true
}
func someFunc(a: AnyObject.Type, b: AnyObject) -> Bool {
return false
}
protocol MyProtocol: ObjcProtocol {
}
class MyBaseClass: MyProtocol {
}
class MyDerivedClass: MyBaseClass {
}
someFunc(ObjcProtocol.self, MyBaseClass())
What should I do?

Nested Swift class can't conform to Comparable

I am trying to implement a simple array based heap but running into issues with the nested Node class. I would like my nodes to be comparable, however, the compiler is complaining that the node class doesn't conform.
import Foundation
class Heap<E:Comparable> {
var heap = Array<Node<E>>()
init() { }
class Node<E:Comparable >:Comparable {
var key:E!
init(key:E) { self.key = key }
}
}
func < <E> (lhs:Heap<E>.Node<E>, rhs:Heap<E>.Node<E>) -> Bool {
return lhs.key < rhs.key }
func == <E> (lhs:Heap<E>.Node<E>, rhs:Heap<E>.Node<E>) -> Bool {
return lhs.key == rhs.key }
It complains because of the Node class doesn't conform the Comparable protocol.
protocol Comparable : _Comparable, Equatable {
func <=(lhs: Self, rhs: Self) -> Bool
func >=(lhs: Self, rhs: Self) -> Bool
func >(lhs: Self, rhs: Self) -> Bool
}
And one more thing, if you want to use the self.key to compare, then the type should conform Comparable protocol as well. Here's the sample:
class Node<E where E:Comparable>:Comparable {
var key:E!
init(key:E) { self.key = key }
}
func ==<E>(lhs: Node<E>, rhs: Node<E>) -> Bool {
return lhs.key == rhs.key
}
func <<E>(lhs: Node<E>, rhs: Node<E>) -> Bool {
return lhs.key < rhs.key
}