How can I override a function with various inherited arguments (Swift) - swift

How to override a function with an inherited argument in Swift?
I have classes:
class ItemA {
var valueA: String?
func setValueA(_ value: String?) {
valueA = value
}
}
class ItemB: ItemA {
var valueB: String?
func setValueB(_ value: String?) {
valueB = value
}
}
// Analog of the abstract class
class ClassA {
func setValues(_ item: ItemA) {
item.setValueA("valueA")
getValues(item) // call getValues from ClassB
}
func getValues(_ item: ItemA) {
abort()
}
}
class ClassB: ClassA {
override func setValues(_ item: ItemB) { // item have type itemB, but extends ItemA
item.setValueB("valueB")
super.setValues(item)
}
override func getValues(_ item: ItemA) {
let item = item as! ItemB
let array = [item.valueA, item.valueB]
print(array)
}
}
My goal is to get the following results:
let itemB = ItemB()
ClassB().setValues(itemB)
// print ["valueA", "valueB"]
I can't override the function in the class because the types are different and there is no type inheritance in Swift. I get this error in setValues(_ item: ItemB) method from ClassB:
Method does not override any method from its superclass
In Java, this can be implemented using an abstract class and an extensible type:
abstract class ClassA {
<T extends ItemA> void setValues(T item) {
item.setValueA("valueA");
getValues(item);
}
abstract void getValues(MainItem item);
}

Correct answer depends on generics:
class ItemA {
var valueA: String?
func setValueA(_ value: String?) {
valueA = value
}
}
class ItemB: ItemA {
var valueB: String?
func setValueB(_ value: String?) {
valueB = value
}
}
// Analog of the abstract class
class ClassA {
func setValues<T : ItemA>(_ item: T) {
item.setValueA("valueA")
getValues(item) // call getValues from ClassB
}
func getValues(_ item: ItemA) {
abort()
}
}
class ClassB: ClassA {
override func setValues<T : ItemB>(_ item: T) {
// item have type itemB, but extends ItemA
item.setValueB("valueB")
super.setValues(item)
}
override func getValues(_ item: ItemA) {
let item = item as! ItemB
let array = [item.valueA, item.valueB]
print(array)
}
}
Check it! If you want to print non-optional values, unwrap them.
let itemB = ItemB()
ClassB().setValues(itemB)
// print ["valueA", "valueB"]

ClassB.setValues can't accept an argument of type ItemB (even though it's a subclass of ItemA), because doing so would violate the Liskov substitution principle.
ClassB instances need to be able to do anything that ClassA instances can. One such requirement is to accept ItemA arguments to its setValues method. Otherwise, what would happen in this code?
let classAInst: ClassA = ClassB()
classAInstance.setValues(ItemA())

Related

Swift method chaining, how to reuse classes and methods?

Consider the following example
class ClassA {
func createAnInstanceOfAnotherClass() -> AnotherClass {
return AnotherClass()
}
func callMeA() {
}
}
class ClassB {
func createAnInstanceOfAnotherClass() -> AnotherClass {
return AnotherClass()
}
func callMeB() {
}
}
class AnotherClass {
func doSomethingAndReturn() {
return
}
}
class MethodChain {
func methodChainTest() {
ClassA()
.createAnInstanceOfAnotherClass()
.doSomethingAndReturn() //return to ClassA
.callMeA() // call classA callMe
ClassB()
.createAnInstanceOfAnotherClass()
.doSomethingAndReturn() // return to ClassB
.callMeB() // call ClassB callMe
}
}
Is it possible for the class AnotherClass to return the instance of the class that created it?
In this example I want to use the class method doSomethingAndReturn when method chaining with both ClassA and ClassB and then contione the method chain with methods from either ClassA or ClassB
You could make AnotherClass generic with a type parameter Creator, which stores the type of its creator.
class ClassA {
func createAnInstanceOfAnotherClass() -> AnotherClass<ClassA> {
return AnotherClass(creator: self)
}
func callMeA() {
}
}
class ClassB {
func createAnInstanceOfAnotherClass() -> AnotherClass<ClassB> {
return AnotherClass(creator: self)
}
func callMeB() {
}
}
class AnotherClass<Creator: AnyObject> {
// weak to avoid retain cycles!
private weak var creator: Creator?
init(creator: Creator) {
self.creator = creator
}
func doSomethingAndReturn() -> Creator {
// assuming you always do method chaining,
// and not do something weird with the intermediate results,
// this should be safe to unwrap forcefully
creator!
}
}

Create a protocol using two classes

I have two classes, something like that
class FirstClass {
func returnInt() -> Int {
return (42)
}
}
class SecondClass {
func printInt(myInt: Int) {
print(myInt)
}
}
I would like to know if it is possible to create a Protocol when the function "returnInt() -> Int" of the FirstClass is call so the function of the second Class "printInt(Int)" is call.
In reality, I'm working on the serialization / deserialization of packet from different classes.
I think is the best way for that, that's why I need your help.
Thank you
Closures
I don't know your exact usage, but one way is using closures instead of protocols. Create closure variable inside first class and then call it after value is returned
class FirstClass {
var valueReturned: ((Int)->Void)?
func returnInt() -> Int {
let value = 42
valueReturned?(value)
return value
}
}
then somewhere where you have references for both instances of both classes set first's valueReturned and inside closure say that when this will be called, you want to call printInt(myInt:) of second's and as parameter pass value from closure
firstClass.valueReturned = { value in // assign parameter of closure
self.secondClass.printInt(myInt: value)
// self.printInt(myInt: value)
}
Delegate Patern
Anyway, if you want to use protocols, you'll need delegate patern.
Start with declaring protocol
protocol FirstClassDelegate: class {
func printInt(myInt: Int)
}
and then create delegate variable inside first class and call method on delegate after value should be returned
class FirstClass {
weak var delegate: FirstClassDelegate?
func returnInt() -> Int {
let value = 42
delegate?.printInt(myInt: value)
return value
}
}
Now implement this delegate protocol to second class and set delegate property of some first class instance as self
class SecondClass {
var firstClass = FirstClass()
init() {
firstClass.delegate = self
}
}
extension SecondClass: FirstClassDelegate {
func printInt(myInt: Int) {
print(myInt)
}
}
This should do it:
class FirstClass {
weak var firstClassToSecondClassCommunicatorDelegate: FirstClassToSecondClassCommunicator?
func returnInt() -> Int {
let myInt = 42
if firstClassToSecondClassCommunicatorDelegate != nil {
firstClassToSecondClassCommunicatorDelegate?.printInt(myInt: myInt)
}
return myInt
}
}
class SecondClass: FirstClassToSecondClassCommunicator {
func printInt(myInt: Int) {
print(myInt)
}
}
class myVC: UIViewController {
override func viewDidLoad() {
let firstClass = FirstClass()
let secondClass = SecondClass()
firstClass.firstClassToSecondClassCommunicatorDelegate = secondClass
}
}
protocol FirstClassToSecondClassCommunicator {
func printInt(myInt: Int)
}
In secondClass initialize your class with:
init(fromFirstClass returnInt: Int) {
....
}

Protocol associatedtype as a type for delegate

The purpose of what I am trying to do is to make it possible to put objects which implements ChildOfRootClass to one array (look at AbstractClass -> children) and put at each ChildNClass instance object a link to its parent (look weak var delegate variable). So I want make type of delegate in each ChildOfRootClass generic.
Hope code will explain what exactly I have meant.
// Parent class for RootClass and Child1Class, Child2Class etc
class AbstractClass {
init() { }
init(smth: String) { }
var children = [String : ChildOfRootClass]()
func add(key: String, child: ChildOfRootClass) {
children[key] = child
}
}
Delegate protocols for each of children.
protocol ChildDelegate: class { }
protocol Child1ClassDelegate: ChildDelegate { func rr() }
protocol Child2ClassDelegate: ChildDelegate { }
class RootClass: AbstractClass {
override init() {
super.init()
}
}
extension RootClass: Child1ClassDelegate {
func rr() { }
}
Children classes.
protocol ChildOfRootClass {
associatedtype ChildOfRootClassDelegateType: ChildDelegate
weak var delegate: ChildOfRootClassDelegateType? { set get }
init(smth: String)
}
class Child1Class: AbstractClass, ChildOfRootClass {
typealias ChildOfRootClassDelegateType = Child1Delegate
weak var delegate: Child1Delegate?
required override init(smth: String) {
super.init(smth: smth)
}
}
extension Child1Class: Child2ClassDelegate { }
class Child2Class: AbstractClass/*, ChildOfRootClass*/ {
required override init(smth: String) {
super.init(smth: smth)
}
}
How I want to use it.
let root = RootClass()
let child1 = Child1Class(smth: "1")
let child2 = Child2Class(smth: "2")
child1.add(key: "child2", child: child2)
root.add(key: "child1", child: child1)

Generic class with generic delegate. How can I distinguish which object's delegate is executing the callback?

MyClass is a generic class which has a generic delegate.
AClass contains two iVar instances of MyClass and also implements MyClassDelegate.
Where AClass implements MyClassDelegate, how can I distinguish which object is calling into the interface? With non-generic classes, == is acceptable.
Please see the comments and error messages at the bottom of this code snippet.
protocol MyClassDelegate: class {
func myClass<T>(_ myClass: MyClass<T>, valueDidChange value: T)
}
class MyClass<T: Comparable> {
private var _value: T
var value: T {
set {
delegate?.myClass(self, valueDidChange: newValue)
}
get {
return _value
}
}
var delegate: MyClassDelegate?
init(value: T) {
_value = value
}
}
class AClass {
private var thing1 = MyClass(value: Int(10))
private var thing2 = MyClass(value: Int(100))
private var thing3 = MyClass(value: TimeInterval(10))
private var thing4 = MyClass(value: TimeInterval(100))
init() {
thing1.delegate = self
thing2.delegate = self
thing3.delegate = self
thing4.delegate = self
}
}
extension AClass: MyClassDelegate {
func myClass<T>(_ myClass: MyClass<T>, valueDidChange value: T) {
// This fails to complile
// Binary operator '==' cannot be applied to operands of type 'MyClass<T>' and 'MyClass<Int>'
if myClass == thing1 {
}
// Binary operator '==' cannot be applied to operands of type 'MyClass<T>' and 'MyClass<TimeInterval>' (aka 'MyClass<Double>')
else if myClass == thing3 {
}
}
}
Restrict the T type in your protocol method signature func myClass<T>(...) to be Comparable. Since you restricted it only in one particular extension of that protocol, the method in AClass can take any kind of T, not just Comparable ones.
I tried and tried but couldn't configure the generic delegate in a manner where I could compare callers.
I read the answer from NRitH, but couldn't get the compiler to accept the syntax. Perhaps there is a way to do this, but I went a different route with success.
I gave up on the protocol/delegate technique and ended up using a callback closure. Instead of defining a delegate in MyClass and implementing that delegate in AClass, I defined a callback closure in MyClass in implemented that in AClass like so:
class MyClass<T: Comparable>: Equatable {
var valueChanged: ((_ clazz: MyClass) -> Void)?
private var _value: T
var value: T {
set {
_value = newValue
valueChanged?(self)
}
get {
return _value
}
}
init(value: T) {
_value = value
}
static public func ==(lhs: MyClass<T>, rhs: MyClass<T>) -> Bool {
return lhs.value == rhs.value
}
}
class AClass {
fileprivate var thing1: MyClass<Int> = MyClass(value: 10)
fileprivate var thing2: MyClass<Int> = MyClass(value: 100)
fileprivate var thing3: MyClass<TimeInterval> = MyClass(value: 10)
fileprivate var thing4: MyClass<TimeInterval> = MyClass(value: 100)
init() {
thing1.valueChanged = { (thing) in
// You can compare here, but you already know which object is callling back
if thing == self.thing1 {
}
}
thing2.valueChanged = { (thing) in
print("Thing2 changed: \(thing.value)")
}
}
}

swift 3 downcast to dynamic class

I am trying to create a couple of objects which are dependent one to each other and they mush have a method to downcast directly the concrete class of the other object. Something like this:
protocol aProt
{
var bVar:bProt! { get set }
}
protocol bProt
{
var aVar:aProt! { get set }
}
class a: aProt
{
var bVar: bProt!
func bConcrete() -> b {
return bVar as! b
}
}
class b: bProt
{
var aVar: aProt!
func aConcrete() -> a {
return aVar as! a
}
Now, the problem is that I want this behavior (func aConcrete(),func bConcrete()) to be inherited by the subclasses of a and b. Then I thought the perfect way of doing this was using generics, but... There's no way of doing this.
class a: aProt
{
var bVar: bProt!
func bConcrete() -> T {
return bVar as! T
}
}
class b: bProt
{
var aVar: aProt!
func aConcrete<T>() -> T {
return aVar as! T
}
You can do it but when you have to use it you must downcast the variable anyway, so there is no way of doing it in a clean manner:
let aObject = a()
let bSubclassObject = a.bConcrete() // The compiler complains it cannot infer the class of T
let bSubclassObject = a.bConcrete() as! bSubclass // this works, but this is exactly which I wanted to avoid... :(
Define the generic function and add where to T:
protocol aProt {
var bVar: bProt! { get set }
}
protocol bProt {
var aVar:aProt! { get set }
}
class a: aProt {
var bVar: bProt!
func bConcrete<T: b>(_ type: T.Type) -> T? {
return bVar as? T
}
}
class b: bProt {
var aVar: aProt!
func aConcrete<T: a>(_ type: T.Type) -> T? {
return aVar as? T
}
}
class a1: a { }
class b1: b {
var fullName: String = "new object"
}
let aObj = a()
aObj.bVar = b1()
let bObj = aObj.bConcrete(b1.self)
bObj?.fullName
According to your requirement, calls bConcrete(b1.self) might still not good enough, but at least you need to know what type of data you are expecting to return.