A way to inherit from multiple classes - swift

I have two classes I want to use in my new class. The first one implements a swipe to delete and the second enables a long press gesture:
class DeleteItem: UITableViewCell {
}
class OpenDetail: UITableViewCell {
}
Since Swift doesn't allow a class to inherit from multiple classes the following example obviously won't work:
class ItemViewCell: DeleteItem, OpenDetail {
}
So in order to create ItemViewCell and having both options, I'll have to have one of the classes to inherit from each other:
class DeleteItem: UITableViewCell {
}
class OpenDetail: DeleteItem {
}
class ItemViewCell: OpenDetail {
}
The problem is, if I only want the long press gesture I'll have to create a new class without inheriting from DeleteItem. Is there a better way of doing this?

This is the perfect case for using Protocols and Protocol extension. A swift protocol is like an interface in Java for example. A protocol can define a set of functions which has to be implemented by the entities which want to conform to this protocol, moreover a protocol can define properties which has to be present in these entities too. For example:
protocol ItemDeleter {
var deletedCount: Int {get set}
func deleteItem(item: ItemType)
}
The problem is, that each entity would have to provide its own implementation of func deleteItem(item: ItemType) even if multiple entities share the same logic of deleting an item, this where a protocol extension comes in handy. For example:
extension ItemDeleter {
func deleteItem(item: ItemType) {
// logic needed to delete an item
// maybe incremented deletedCount too
deletedCount++
}
}
Then you could make your ItemViewCell conform to the ItemDeleter protocol, in this case all you need is to make sure that ItemViewCell has a property deletedCount: Int. It does not need to provide an implementation for func deleteItem(item: ItemType) as the protocol itself provides a default implementation for this function, however you can override it in your class, and the new implementation will be used. The same applies for DetailOpener protocol.

Related

Swift protocol to only implemented by specific classes

I want to create a protocol which is only adopted by a specific class and its subClassses in swift.
I know i can use protocol extensions like this
protocol PeopleProtocol: class {
}
extension PeopleProtocol where Self: People {
}
But the method that will go in my protocol will be an init method which will be implemented by a class or its subClasess and will return only some specific type of objects.
some thing like this.
protocol PeopleProtocol: class {
init() -> People
}
or i can do some thing like this
extension PeopleProtocol where Self : People {
init()
}
But there are two problems,
In the first approach if i put an init method in the protocol it don't allow me to put a return statement there like -> People in the first approach.
In the second approach i have to provide a function body in the protocol extensions, so this thing will be out of question, as i don't know what specific type to return for this general implementation.
So any suggestions how i can call an init method and do either:
Let the protocol (not protocol extension) to be implemented by only specific classe and its subClasses.
Or return an instance of a certain from protocol extension method without giving its body.
You could add a required method that you only extend for the appropriate classes.
for example:
protocol PeopleProtocol
{
var conformsToPeopleProtocol:Bool { get }
}
extension PeopleProtocol where Self:People
{
var conformsToPeopleProtocol:Bool {return true}
}
class People
{}
class Neighbours:People
{}
extension Neighbours:PeopleProtocol // this works
{}
class Doctors:People,PeopleProtocol // this also works
{}
class Dogs:PeopleProtocol // this will not compile
{}
This could easily be circumvented by a programmer who would want to, but at least it will let the compiler warn you if you try to apply the protocol to other classes.

Swift extension for selected class instance

In Objective-C category, you can bring in the extended capability introduced by the category methods by including the header of the category in your class.
It seems like all Swift extensions are automatically introduced without import. How do you achieve the same thing in Swift?
For example:
extension UIView {
// only want certain UIView to have this, not all
// similar to Objective-C, where imported category header
// will grant the capability to the class
func extraCapability() {
}
}
Define a protocol that will serve as a selection, wether the extensions should be available or not:
protocol UIViewExtensions { }
then define an extension for the protocol, but only for subclasses of UIView (the other way around won't work):
extension UIViewExtensions where Self: UIView {
func testFunc() -> String { return String(tag) }
}
A class that is defined to have the protocol will also have the extension:
class A: UIView, UIViewExtensions { }
A().testFunc() //has the extension
And if it is not defined to have the protocol, it will also not have the extension:
class B: UIView {}
B().testFunc() //execution failed: MyPlayground.playground:17:1: error: value of type 'B' has no member 'testFunc'
UPDATE
Since protocol extensions don't do class polymorphism, if you need to override functions, the only thing I can think of is to subclass:
class UIViewWithExtensions: UIView {
override func canBecomeFocused() -> Bool { return true }
}
UIViewWithExtensions().canBecomeFocused() // returns true
this could also be combined with the extension, but I don't think it would still make much sense anymore.
You can make extensions private for a particular class by adding private before the extension like so
private extension UIView {
func extraCapability() {
}
}
This will mean it can only be used in that particular class. But you will need to add this to each class that requires this extension. As far as I know there is no way to import the extension like you can in Obj-c
NOTE
Private access in Swift differs from private access in most other languages, as it’s scoped to the enclosing source file rather than to the enclosing declaration. This means that a type can access any private entities that are defined in the same source file as itself, but an extension cannot access that type’s private members if it’s defined in a separate source file.
According to Apple, here, it does not appear you can make extensions private in separate files.
You can create a private extension in the same source file.

Can a Swift class be extended multiple times with the same methods?

I am designing a framework that uses protocols and extensions to allow for third-parties to add support for my framework to their existing classes.
I'd also like to include some built-in extensions for known classes like UIView, but I don't want to prevent users from defining their own additional support for the same classes.
My question is is there any way that I can extend the same class twice, and override the same (protocol) method in that class both times, while still having some way to call the other if the first one fails.
Elaboration: I really have three goals here I want to achieve:
I want to allow users of my framework to provide their own extensions for their own (or any) UIView subclasses.
I also need some way to allow general behavior that can apply to all UIViews as a fallback option (i.e. if the specific class extension can't handle it, fall back on the generic UIView extension).
I'd also like to separate out my own implementation, by providing some built-in generic view handling, but in such a way that it doesn't prevent third parties from also defining their own additional generic handling. (If I can't do this, it's not a big deal, the first two parts are the most important.)
I have part 1 working already. The problem is how to get this fallback behavior implemented. If I do it all with extensions, the subclass will override the superclass's implementation of the protocol method. It could call super.method, but I'd like to avoid putting that responsibility on the subclass (in case the author forgets to call super).
I'd like to do this all from the framework code: first, call the object's protocol method. If it returns false, I'd like to somehow call the generic UIView handler.
Now that I'm typing it all out, I'm wondering if I can just use a different method for the generic fallback and be done with it. I just figured it would be elegant if I could do it all with one method.
No! It can't be extended multiple times.
extension Int {
var add: Int {return self + 100} // Line A
}
extension Int {
var add: Int {return self + 105} //Line B
}
Doing so would create a compile time error ( on Line B) indicating: Invalid redeclaration of 'add'
Swift is a static typing language and helps you find these sorts of errors before runtime
In Objective-C you can write this and still not get an error, however the result would be undefined, because you wouldn't know which method gets loaded first during runtime.
Overriding a single protocol method twice in 2 separate extensions wouldn't work, because the protocol method names would collide. Once compiled, they're all just methods on the same class. With that in mind, perhaps put all the protocol methods in their own extension & call them from within the other ones?
The following could be one general option. Could get messy if you decide to keep adding additional extension functionality.
class baseClass {
//stuff
}
extension baseClass: myProtocol {
override func myProtocolMethod(args) -> returnType {
//Repeat this in a separate extension & your method names collide
var status: Bool
//protocol method code sets status as appropriate...
return status = true ? optOne(status) : optTwo(status)
}
func optOne(status:Bool) -> returnType{
//do the 'true' thing
return returnType
}
func optTwo(status:Bool) -> returnType{
//do the 'false' thing
return returnType
}
}
extension baseClass {
var oneExtension = myProtocolMethod(someArg)
}
extension baseClass {
var twoExtension = myProtocolMethod(someArg)
}
I realize this Question is over a year old and the original poster has probably moved on to other things, but I'd like to share an idea anyways and perhaps get some feedback.
You say that you want a method that can be overwritten multiple times. The short answer, like many in this thread have given is no, but the long answer is yes.
We can solve the issue with a bit of generic magic.
class MyView: UIView {
var customizer: MyProtocol<MyView> = Defaults()
func willCallCustomizer() {
customizer.coolMethod(self)
}
}
// Use this class as if it were a protocol
class MyProtocol<T: UIView>: NSObject {
func coolMethod(_ view: T) {}
}
// Class inherits from the "protocol"
class Defaults: MyProtocol<MyView> {
override func coolMethod(_ view: MyView) {
// Some default behavior
}
}
/// on the clients end...
class CustomerCustomizer: MyProtocol<MyView> {
override func coolMethod(_ view: MyView) {
// customized behavior
}
}
So if the client wants to use their own customizer they can just set it, otherwise it will just use the default one.
myViewInstance.customizer = CustomerCustomizer()
The benefit of this approach is that the client can change the customizer object as many times as they want. Because MyProtocol is generic, it may be used for other UIView's as well; thus fulfilling the role of a protocol.

Why use class only protocols in Swift?

Can anyone please explain class only protocols to me in Swift. I understand what protocols are and why we use them. I also understand that its recommended to use class only protocols when we use reference type objects in it and want to limit the protocol conformation to classes only. However, I can't find any good answer to support that recommendation. Why is it recommended? What is the drawbacks of using normal protocols in that case.
One use case:
You have a "delegate" protocol and someone wants to have a weak property of that protocol type. weak can only be used on reference types; therefore, the protocol must be class-only.
Another use case used to be to extend reference types to adopt protocols. You can't extend AnyObject itself (to inherit from another protocol, or for any other reason) but you have any reference types you want adopt a protocol inherited from AnyObject.
For example, having class equality based on unique identity is often a perfectly fine solution, so you could adopt EquatableObject:
public protocol EquatableObject: AnyObject, Equatable { }
public extension EquatableObject {
static func == (class0: Self, class1: Self) -> Bool {
class0 === class1
}
}
But now, we have protocol extension constraints (using where clauses), so instead of extending AnyObject, we can extend the protocol, and use AnyObject as a constraint. It looks backwards but operates identically, and removes the need for our own protocol. 🥳
public extension Equatable where Self: AnyObject {
static func == (class0: Self, class1: Self) -> Bool {
class0 === class1
}
}

Swift: Property conforming to a specific class and in the same time to multiple protocols

In Objective-C, it's possible to write something like that:
#property(retain) UIView<Protocol1, Protocol2, ...> *myView;
But how can I write this code in swift?
I already know how to make a property conform to many protocols, but it does not work by using the inheritance:
var myView: ??? protocol<Protocol1, Protocol2, ...>
Edit:
I use many UIView subtypes like UIImageView, UILabel or others, and I need to use some of the UIView properties plus some methods defined in the protocols. In the worst case I could create a UIViewProtocol with the needed properties, but I would know if it is possible in Swift to declare a property/variable with a type and some protocol to conform with.
You can do this with a generic class using a where clause:
A where clause enables you to require that an associated type conforms
to a certain protocol, and/or that certain type parameters and
associated types be the same.
To use it, make the class your property is defined in a generic class with a type constraint to check if the type parameter for your property matches your desired base class and protocols.
For your specific example, it could look something like this:
class MyViewController<T where T: UIView, T: Protocol1, T: Protocol2>: UIViewController {
var myView: T
// ...
}
In Swift 4 it's finally possible. You can declare variable of some class conforming to protocol at the same time, like this:
class ClassA {
var someVar: String?
}
protocol ProtocolA {}
class ClassB {
var someOptional: (ClassA & ProtocolA)? // here is optional value
var some: ClassA & ProtocolA // here is non-optional value; need to provide init though :)
}
One and probably a bit ugly one of the ways to do that, is to create a wrapper protocol for UIView:
protocol UIViewRef {
var instance: UIView { get }
}
Now it is possible to create a protocol which implements Protocol1, Protocol2 and UIViewRef, which is going to be used to get the UIView itself:
protocol MyUIViewProtocol: UIViewRef, Protocol1, Protocol2 { }
And last step will be implementing UIViewRef protocols for your UIViews, which, in you case, as I understand, already implement Protocol1 and Protocol2:
// SomeOfMyViews already implements Protocol1 and Protocol2
extension SomeOfMyUIViews: MyUIViewProtocol {
var instance: UIView { return self }
}
As the result we have MyUIViewProtocol, implementers of which hold a reference to a UIView and each of them implement
Protocol1 and Protocol2. One caveat though - to get the UIView itself, we need to ask it's reference from instance
property. For example
// Lets say we're somewhere in a UIViewController
var views: [SomeOfMyUIView] = // Get list of my views
views.forEach { self.view.addSubview($0.instance) }