Swift method chaining, how to reuse classes and methods? - swift

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!
}
}

Related

How to return subclass objects from its base class static method?

In Swift, I want to make my base class static method return its subclass objects when the static method is called from a subclass.
When returning one subclass object, I can make it possible by using init().
But when returning multiple subclass objects, init() can not be used.
And I want to not only just return subclass objects from the parent static method, but also to implement some logic other than instantiation in the parent static method, and make the static method of each subclass inherit the parent's static method behavior.
I have 3 sub-classes. So, I don't want to write the same code in the static methods of 3 sub-classes.
How should I do?
If possible, I want to use the static method instead of init() to return a single subclass object, too.
class Base {
func f() {
print("base class")
}
// this does not works. it creates a base class object.
static func createSubclassObject() -> Base {
return Base()
}
// this works. it creates a subclass object.
init() {
}
// this does not work. base class objects are created.
static func createSubclassObjects(count: Int) -> [Base] {
var objects = [Base]()
for _ in 0 ..< count {
objects.append(Base())
}
return objects
}
/* probably I need something like this. but this code generates a compile error
static func createSubclassObjects(count: Int) -> [Self] {
var objects = [Self]()
for _ in 0 ..< count {
objects.append(Self())
}
return objects
}
*/
// generic also does not work. this returns a base class object.
static func createSubclassObjectByGeneric<T: Base>() -> T {
return T()
}
}
class Sub: Base {
override func f() {
print("sub class")
}
}
print(Sub().f())
// sub class・
print(Sub.createSubclassObject().f())
// base class
Sub.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// base class
// base class
print(Sub.createSubclassObjectByGeneric().f())
// base class
You need to return Self, not Base.
static func createSubclassObject() -> Self {
.init()
}
required init() { }
Also, don't use a for loop. There is an array initializer premade for what you're doing.
static func createSubclassObjects(count: Int) -> [Base] {
.init(repeating: createSubclassObject(), count: count)
}
The following code works. But I think there should be better solutions because I don't want to define class func sub() in the parent class and override class func sub() in each sub class.
EDIT: See the Jessy's answer, which is the better solution.
class Base {
func f() {
print("base class")
}
static func createSubclassObjects(count: Int) -> [Base] {
var objects = [Base]()
for _ in 0 ..< count {
//objects.append(Base())
objects.append(Self.sub())
}
return objects
}
class func sub() -> Base {
Base()
// or use fatalError() if you don't need to call createSubclassObjects(count: Int) from the base class
}
}
class Sub1: Base {
override func f() {
print("sub1 class")
}
override class func sub() -> Base {
Sub1()
}
}
class Sub2: Base {
override func f() {
print("sub2 class")
}
override class func sub() -> Base {
Sub2()
}
}
Base.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// base class
// base class
Sub1.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// sub1 class
// sub1 class
Sub2.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// sub2 class
// sub2 class

overriding declarations in extensions is not supported - swift

I made a minimal reproducible code of my issue.
enum Animal {
case cat
case dog
}
protocol AdoptPet {
func petIs(pet: Animal)
}
class Delegate {
}
extension Delegate: AdoptPet {
func petIs(pet: Animal) {
print("not implemeted")
}
}
class Girl: Delegate {
}
extension Girl {
override func petIs(pet: Animal) { // overriding declarations in extensions is not supported
print(pet)
}
}
class PetCenter {
init () {
}
func setup(adpoter: Delegate){
let pet: Animal = .cat
adpoter.petIs(pet: pet)
}
}
let petCenter = PetCenter()
let adpoter: Girl = Girl()
petCenter.setup(adpoter: adpoter)
What should I change in the code to make this compile ?
You need to move both the declaration of the function and the override into the type declarations from extensions. So Delegate needs to contain the petIs implementation in its declaration and Girl needs to override the petIs function in its body as well (using the override keyword) rather than in an extension.
class Delegate: AdoptPet {
func petIs(pet: Animal) {
print("not implemeted")
}
}
class Girl: Delegate {
override func petIs(pet: Animal) {
print(pet)
}
}
class PetCenter {
init () {
}
func setup(adopter: Delegate){
let pet: Animal = .cat
adopter.petIs(pet: pet)
}
}
let petCenter = PetCenter()
let adopter = Girl()
petCenter.setup(adopter: adopter) // cat

How can I override a function with various inherited arguments (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())

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) {
....
}

Can I have a subclass of my class as property in Swift?

In Swift 2.1 I need to initialize every properties before use the class method. But if I want to have a property that is a subclass of it, I will have an infinite loop. Is this possible?
class Myclass {
let mySubClass:SubClass
init() {
mySubClass = SubClass()
print("Init my class")
}
}
class SubClass:Myclass {
override init() {
print("Init subclass")
}
}
let myClass = Myclass()
You could use a lazy stored property.
The instance of the subclass isn't initialized until it's used the first time.
class Myclass {
lazy var mySubClass : SubClass = {
return SubClass()
}()
init() {
print("Init my class")
}
}
class SubClass:Myclass {
override init() {
print("Init subclass")
}
}
let myClass = Myclass()
myClass.mySubClass
I think you're better off to be explicit about the relationships. Something like:
class Myclass {
var mySubClass:SubClass?
init() {
print("Init my class")
}
}
class SubClass:Myclass {
override init() {
print("Init subclass")
}
}
var myClass = Myclass()
let mySub = SubClass()
myClass.mySubClass = mySub