1

I have a class A that holds an object B implementing the protocol P.

I would like to forbid any modification to object B without class A acknowledging it. Is it possible without any delegate or mutual reference?

Considering that it is possible to specify a protocol that can only be implemented by class type objects protocol P: class {} , if there is something similar for structs, I could bind the protocol to a struct, makeing it explicit (being known that structs are passed by value) that the object B has to be set but not edited.

Long story short: Is there a way to force a protocol implementation to be a struct?

Paulw11
  • 108,386
  • 14
  • 159
  • 186
jalone
  • 1,953
  • 4
  • 27
  • 46
  • 1
    No, there is not: [How to restrict a protocol to value types only?](https://stackoverflow.com/questions/33623104/how-to-restrict-a-protocol-to-value-types-only). – Martin R Apr 24 '18 at 11:50

2 Answers2

1

The only I would suggest is to wrap class A by a protocol Q and define a variable setter of an instance of protocol P inside.

protocol Q {
    var p: P? { get set }
}

class A : Q {
    var p: P? {
        get {
            // logic
        }
        set {
            //logic
        }
    }
}
Eugene Berdnikov
  • 2,150
  • 2
  • 23
  • 30
Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
0

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"
}
Maxim Kosov
  • 1,930
  • 10
  • 19
  • 1
    The problem is that i have no control over the holding class and this will perform downcast and checks on the real object type (i know all the problematic coming with this, but i can't do anything about it), so i would like to at least enforce kind of a c++ "const-like" approach. Thank you anyway. – jalone Apr 24 '18 at 12:42
  • I'm not I understand about not having control over holding class. You mean it's in third-party library or what? – Maxim Kosov Apr 24 '18 at 13:28
  • 1
    Yes, kind of a third party lib, I guess i'll just adopt an "enforce by documentation" approach. with a big DO NOT APPLY SIDE EFFECTS note to the doc of the protocol, otherwise yes, your approach would be optimal. – jalone Apr 24 '18 at 13:31
  • Does it makes sense to wrap holding class into your own? Or extend it to conform a protocol and then use protocol everywhere. `extension ThirdPartyClass: FooImmutable { }` – Maxim Kosov Apr 24 '18 at 13:43
  • Sadly not possible. – jalone Apr 24 '18 at 13:59