1

I know about protocols and protocol extensions being the best way to emulate abstract classes, but what I want to do needs real abstract classes I think.

I want a BaseCollectionViewCell and a BaseCollectionViewSource that work together. You'd pass an array to a subclass of the BaseCollectionViewSource and implement a method that returns a reuse identifier. The cell would be instantiated by the BaseCollectionViewSource and have a method setData that would be overridden in the concrete collectionViewCell.

What I practically want to do is this:

abstract class WRBaseCollectionViewCell: UICollectionViewCell {
    abstract func setData(_ data: AnyObject)
}

But I can't emulate this with Swift (I think). Protocols can't inherit from classes and there is no dynamic dispatch, which kills my idea for everything to be overridable.

Does anyone have an idea how to do this? A factory maybe? I want to make this as easy as possible to implement a new collectionView.

vrwim
  • 13,020
  • 13
  • 63
  • 118
  • Swift doesn't have abstract classes. and IMO it doesn't need them. With generics and protocols — especially with *protocol extensions* — swift offers a rich toolset. – vikingosegundo Feb 01 '17 at 23:30
  • @vikingosegundo do you have a concrete solution to my issue? I'm not asking for the language to be changed, I want to implement this as best as possible. – vrwim Feb 01 '17 at 23:32
  • because of your specific example: you might have a look on a project I recently started: [TaCoPopulator](https://github.com/vikingosegundo/TaCoPopulator), a datasource framework for collection and tableviews. – vikingosegundo Feb 01 '17 at 23:33
  • honestly I don't understand what you try to say here: *Protocols can't inherit from classes and there is no dynamic dispatch, which kills my idea for everything to be overridable.* – vikingosegundo Feb 01 '17 at 23:37
  • 1
    @vikingosegundo I want all my methods to be overridable in a concrete class, but without dynamic dispatch, there is no way to do this by using protocol extensions. Also, I can't make my protocols inherit from `UICollectionViewCell`, it isn't nice that I have to implement both `UICollectionViewCell` and my protocol and constantly use `as!` to use them. Things like these are possible in languages with abstract classes, like Java and C#. I just want to know what the best way to do this in Swift is. – vrwim Feb 01 '17 at 23:44
  • Certain aspects of what you said so far make me believe, that you are using the tool "abstract class" wrongly and dangerously anyway. *I want a BaseCollectionViewCell and a BaseCollectionViewSource that work together*. If you mean by this, that an abstract class implements several protocols, it is a huge and strong indication for (very) smelly code, as it most likely describes a [God class](https://en.wikipedia.org/wiki/God_object). – vikingosegundo Feb 02 '17 at 00:04
  • you should extend your tool belt by looking at different approaches. One resource I found very helpful are the [SOLID Principles](https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)). and of course [Composition over inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance) – vikingosegundo Feb 02 '17 at 00:05

2 Answers2

4

For reference, there is a proposal to add Abstract classes/methods but it is currently differed. I'm guessing they will re-examine it in the next year or two.

The way I accomplish this type of thing is by using protocols with associated types:

protocol ViewModelUpdatable {
    associatedtype ViewModelType
    func update(with viewModel: ViewModelType)
}

Then simply make your class adhere to it, and it will force you to add:

func update(with viewModel: WhateverTypeYouWant) {
    //update your class
}

The advantage of this approach, is it's possible to deal with a class in a more generic way, but keep type safety.

The way I'm hoping to deal with this some day is generics, but InterfaceBuilder still breaks with generics .

Community
  • 1
  • 1
GetSwifty
  • 7,568
  • 1
  • 29
  • 46
1

Hmm, not quite sure what you want. Take a look at the following protocol.

protocol SetDataViewCell {}

extension SetDataViewCell where Self: UICollectionViewCell {
    func setData(_ data: AnyObject) {}
}
J.Wang
  • 1,136
  • 6
  • 12