How to Restrict a Protocol to Value Types Only

Protocol only implemented by struct or immutable

Protocols shouldn't be used this way. Protocols is to define behaviour, not the exact shape of object.

I assume by restricting protocol to structs you want to achieve immutability of it's implementers. If so we can design protocol with getters only

protocol Foo {
var foo: string { get }
}

This way Foo is immutable and it's can't be changed from anywhere no matter if it's struct or class.

Then, we can inherit FooMutable from Foo and add mutators there

protocol FooMutable: Foo {
var foo: string { get set }
}

Finally class A is the only place where we can mutate Foo:

class A {
private var fooValue: FooMutable = FooImpl()

var foo: Foo { get { return fooValue } }

func mutateFoo() {
fooValue.foo = "bar"
}
}

class FooImpl: FooMutable {
var foo = "foo"
}

Why Swift protocol conforming values are treated as Value types by default?

Your protocol SampleProtocol could be adopted by a class or a struct. Swift is using the behavior of the value type which is the more restrictive type until you tell it that the protocol will only be used by a class reference type.

Add conformance to AnyObject to your protocol to get reference type behavior:

protocol SampleProtocol: AnyObject {
var message: String? { get set }
}

See The Swift 5.1 Programming Guide - Class-Only Protocols for more details.

The guide notes:

Use a class-only protocol when the behavior defined by that protocol’s
requirements assumes or requires that a conforming type has reference
semantics rather than value semantics.


Historical note: Using class keyword:

Prior to Swift 4.0, this was written using the class keyword:

protocol SampleProtocol: class {
var message: String? { get set }
}

This still works for the time being, but it is currently just a type alias for AnyObject and will likely be removed in a later version of Swift.

Swift protocol to only implemented by specific classes

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.

Can you restrict a Swift generic constraint to a set of known types?


Can I "or" the constraints somehow?

No, you cannot. However, this will accomplish the same objective.

Define a new protocol:

protocol MetadataRawValue { }

Add your conforming types:

extension Double: MetadataRawValue { }

extension Bool: MetadataRawValue { }

extension String: MetadataRawValue { }

And finally:

struct MetadataValue<T> where T: MetadataRawValue {
...
}

Is a protocol either a reference or value type in Swift?


I don't think this should increase the reference count:

var transferServiceScanner: TransferServiceScanner increases the reference count to one, since all references are strong if they are not declared weak or sth else.

Storing the delegate variable as weak makes sure strong references do not go both ways and so ARC can deinit them.

I'm trying to figure out if a class were to simply conform to a protocol, does this create a reference?

A class is always a reference-type, whether you refer to it through a protocol or directly. So assigning a protocol with a reference-type(class) behind it does not copy the class-object, but you rather give out another reference to the object and increases the reference-count which ARC looks at.

With

protocol TransferServiceScannerDelegateProtocol: NSObjectProtocol {

you are making sure, that only a class can implement the protocol, that is why you can declare weak var delegate: TransferServiceScannerDelegateProtocol, because only classes can implement NSObjectProtocol with NSObject & co.

Without declaring a protocol class-only, either a struct or a class, both can implement the protocol. But only if you restrict the protocol to class-only can you use the protocol as if it were a class, using things like weak with it.



Related Topics



Leave a reply



Submit