I have a property and a method:
class C {
var myProperty = ""
func myFunc() {
}
}
I would like to have a rule that when you set myProperty you must then proceed to call myFunc. Of course I can have a mental rule that requires this, but a mental contract is no contract at all. I want to enforce this contract through the class's API.
(NOTE All of this is purely about what goes on inside C. Both myProperty and myFunc can be private as far as visibility outside C is concerned; that doesn't affect the problem.)
Obviously we can do this with a setter observer:
class C1 {
var myProperty = "" {
didSet {
self.myFunc()
}
}
func myFunc() {
}
}
However, there's something I don't like about that solution: it relies upon what amounts to a hidden side effect. It is up to me to know that saying self.myProperty = "..." also triggers a call to myFunc. I don't like that kind of hidden side effect; it makes my code harder to understand, and violates one of my key programming principles, Say What You Mean.
What do I mean? I mean something like this:
self.setMyPropertyAndCallMyFunc("...")
I like that, because it tells me exactly what this call does every time it occurs in my code. So we could write this:
class C2 {
var myProperty = ""
func myFunc() {
}
func setMyPropertyAndCallMyFunc(_ s:String) {
self.myProperty = s
self.myFunc()
}
}
But there's a problem with that, namely that it is now possible to set myProperty without calling myFunc, breaking the rule that we set out to enforce in the first place! The only way I've found to enforce that rule is to have another class that defends the property with privacy. For example:
class C3 {
class Inner {
private(set) var myProperty = ""
private func myFunc() {
}
func setMyPropertyAndCallMyFunc(_ s:String) {
self.myProperty = s
self.myFunc()
}
}
let inner = Inner()
}
That is in fact what I'm doing, but it seems a bit nutty to have a second class just to enforce these privacy and naming rules. My question is: Is there another way?
Yes, though I don't know if it's actually any better. You can hide myProperty inside of a closure rather than inside of a class/struct. For example:
class C {
public var myProperty: String { return _myPropertyGetter() }
public func setMyPropertyAndCallMyFunc(value: String) {
_myPropertySetter(self, value)
}
func myFunc() {
print("myFunc")
}
private let (_myPropertyGetter, _myPropertySetter): (() -> String, (C, String) -> ()) = {
var property = ""
return ({ property }, { property = $1; $0.myFunc() })
}()
}
let c = C()
c.myProperty
c.setMyPropertyAndCallMyFunc(value: "x")
c.myProperty
There's a lot of complexity here, like passing self to _setMyPropertyAndCallMyFunc to allow myFunc to live outside the closure, and maybe some of that could be dispensed with. But the basic idea is to generate two functions that are the only functions that have access to the property storage, making it "super-private" without creating an inner class.
If you don't need myFunc() to be public (and from your Inner example, I think you don't), then you can do it a little simpler, and this almost might be better than Inner.
class C {
public var myProperty: String { return _myPropertyGetter() }
public func setMyPropertyAndCallMyFunc(value: String) { _myPropertySetter(value) }
private let (_myPropertyGetter, _myPropertySetter): (() -> String, (String) -> ()) = {
var property = ""
func myFunc() {
print("myFunc")
}
return ({ property }, { property = $0; myFunc() })
}()
}
Related
I am experimenting with a basic proxy pattern in Swift playgrounds; I am not 100% familiar with it; but some videos are helping.
In my experiment, the subject, C is called through a proxy to perform said actions
ie:
A - Proxy - C
However, in my experiments I find out I can just call C itself directly, without even needing the proxy; so I am left wondering why bother with a proxy when I can call C directly anyway?
So I decided to make the variables in C private; but now I can't call them, or make modifications, and I am not sure how to resolve it.
I also tried a "decorator" pattern I found on stackoverflow to try to manipulate Cs variables, but still its marked private, so its not possible.
Also, the decorator pattern I found uses static variables. This makes me think well, why not just write a static function that creates c in memory, and then update the reference in proxy to that of the results of the static function.
I guess what I'm mis-understanding here is what is the point of a proxy class if you can just call the subject (in this case C) directly anyway?
Examples use Swift playground:
class A {
let proxy: Proxy = Proxy()
var funds: Int {
return self.proxy.funds
}
}
class Proxy {
private let c: C = C()
public var funds: Int {
return c.funds
}
private func canIGetFunds() -> Bool {
guard (self.funds > 0) else {
return false
}
return true
}
func subtractFunds(funds: Int = 0) {
if (canIGetFunds()) {
print ("you have enough funds")
willDebit(funds: funds)
}
else {
print ("Not enough funds")
}
}
private func willDebit(funds: Int = 0) {
self.c.funds -= funds
}
}
class C {
private (set) var funds: Int = 100
}
let a = A()
print (a.funds)
a.proxy.subtractFunds(funds: 50)
This code will throw up a compiler error on:
self.c.funds -= funds
because:
funds setter is inaccessible
the funds variable is indeed private.
So, I tried a decorator too; code I found from stackoverflow (its not mine):
#propertyWrapper
struct Announced<T, U> {
private var announcedFunction: (T) -> U
var wrappedValue: (T) -> U { announcedFunction }
init(wrappedValue: #escaping (T) -> U) {
announcedFunction = { args in
let rv = wrappedValue(args)
print("In: \(args)")
print("Out: \(rv)")
return rv
}
}
}
extension Wallet {
#Announced static var add: ((Int, Int)) -> Int = { $0.0 + $0.1 }
#Announced static var subtract: ((Int, Int)) -> Int = { $0.0 - $0.1 }
}
Now here the add and subtract are static variables; and the contents of the closure are of course wrong because I make no reference to the actual Wallet variables -- I've only put it like this to help with discussion.
The way I got around it is to try to make the (Int, Int) take in a Wallet class, and then return a modified Wallet object where the add or subtract has been completed
So something like this:
#Announced static var subtract: ((w:Wallet, Int)) -> Wallet = {
let newWallet = Wallet()
newWallet.cash = w.cash
newWallet.cash -= $0.1
return newWallet
}
But if I do this pattern, I don't see why I don't just write a static function and disregard this decorator.
I've even tried making C follow a delegate pattern where the Wallet is a delegate of C and adds, subtracts funds; but this too has an issue in that you can call C directly and because is its own delegate it has no reason to fail or throw up an error, etc.
So anyway, probably I'm just overcomplicating:
Whats the point of having a proxy if you can just call the subject directly and do your manipulation that way?
Is there a way to make the proxy pattern the only way you can call and make actions on the subject?
With thanks?
The easiest way is using public/internal setter
class C {
var funds: Int = 100
}
But if you define C in this same file with Proxy then you can use fileprivate(set) access modifier
class Proxy {
...
}
class C {
fileprivate(set) var funds: Int = 100
}
I expected the following code to print "extension" in both cases. But the type constraint on the extension does not take effect on the contained generic type. I see the same behavior when constraining on protocols too.
class Generic1<T1> {
func doSomething() {
print("base")
}
}
extension Generic1 where T1 == String {
func doSomething() {
print("extension")
}
}
class Generic2<T2> {
private let generic1 = Generic1<T2>()
func doSomething() {
generic1.doSomething()
}
}
Generic1<String>().doSomething() // prints extension
Generic2<String>().doSomething() // prints base
The only workaround I currently have is to constrain the outer generic as well like so:
extension Generic2 where T2 == String {
func doSomething() {
generic1.doSomething()
}
}
Why does this happen? Are there better solutions?
Edit: Just for completeness, the workaround that suited my case was the following:
class Generic1<T1> {
func doSomething() {
print("base")
}
}
class StringGeneric1: Generic1<String> {
override func doSomething() {
print("extension")
}
}
class Generic2<T2> {
private let generic1: Generic1<T2>
init (_ generic1: Generic1<T2>) {
self.generic1 = generic1
}
func doSomething() {
generic1.doSomething()
}
}
Generic1<String>().doSomething() // prints "base"
Generic2<String>(StringGeneric1()).doSomething() // prints "extension"
The problem is that methods defined in extensions are statically dispatched. So when you have:
class Generic2<T2> {
private let generic1 = Generic1<T2>()
func doSomething() {
generic1.doSomething()
}
}
The compiler cannot know here whether T2 is going to be a String or not, so it generates a call to the method in the base class. When you explicitly specify that T2 is String, then with that information, the compiler can generate a call to the extension's method here. Otherwise, though, the type of T2 isn't known until runtime, so you can't reach the extension method via static dispatch.
This may be solved when conditional conformances are added with Swift 4.2
I would like to override a setter/getter one time for but for all the properties for a class in swift
This my class. I want to call Realm each time I am adding a new value
class House : Object
{
var a:String
{
set {
do {
let realm = try Realm()
try realm.write {
a = newValue
}
}
catch {
}
}
}
var b:String
{
set {
do {
let realm = try Realm()
try realm.write {
b = newValue
}
}
catch {
}
}
}
}
There is no way in Swift how you can overwrite setters for all properties at once.
What you could generally do though is use:
overwritten setters per property
abstract computed properties wrapping low-level properties
intercept getters and setters by KVC accessor methods (e.g. is<Key>, get<Key>, …) and rely only on untyped dynamic KVC-based access via valueForKey(Path):, if you want to apply the decorated behavior (which you might want to avoid for this reason)
But Realm is using custom getters and setters under the hood, which are dynamically overwritten in an dynamically inserted intermediate class at runtime and relies on the presence of those. So the only approach, which is really feasible is having dynamic stored properties declared and adding for each of those an extra property, based on those.
var storedPropertyA: String = ""
var computedPropertyA: String {
get {
// add your extra behavior here
return storedPropertyA
}
set {
// add your extra behavior here
self.storedPropertyA = newValue
}
}
Beside that there is an alternative way of using the decorator pattern and decorate your whole object with extra behavior. In Swift, you could have your object and your decorator implement a common protocol, which defines your properties.
protocol HousingProperties {
var a: String { get set }
}
class House: HousingProperties {
var a: String = ""
}
class HouseDecorator: HousingProperties {
internal var house: House
init(house: House) { self.house = house }
var a: String {
// add your extra behavior here
self.house.a = a
}
}
Still I would NOT recommend to intercept property setters and getters for the purpose you intend here. Instead I'd advise to structure your application's architecture in a way, that allows you to be aware whether there is a write transaction or not and let the responsibility of making a write transaction in the hands of the code, which tries to modify objects.
Let me explain why:
Realm is using a multiversion concurrency control algorithm to manage persisted data and achieve thread-safety. This makes sure that different threads can read data at any point in time without having to read-lock and trying to synchronize these. Instead when a write is happening, all accessors are notified that there is new data and try to move on to the newest transaction. Until that has happened, all versions between the oldest data version, which is still used by a thread and the one written have to be retained. They can be first released when all threads advanced their commit pointers. If you do a lot of small transactions, you risk that your file size will blew up to unnecessary high values. For that reason, we recommend to batch write transactions to large changesets.
There is one hack to kind of attain what the poster is looking for, however possibly not advisable... Anyway; you can can create your own assignment operators that does whatever you want to do in realm prior to assigning the values
class MyType {
var myInt : Int = 0
var myString : String = ""
init(int: Int, string: String) {
myInt = int
myString = string
}
}
infix operator === {}
func ===<T>(lhs: T, rhs: T) -> T? {
Realm() // replace with whatever Realm()-specific stuff you want to do
return rhs
}
protocol MyAddableTypes {
func + (lhs: Self, rhs: Self) -> Self
}
extension String : MyAddableTypes {}
extension Int : MyAddableTypes {}
infix operator +== {} // ... -== similarily
func +==<T: MyAddableTypes>(lhs: T, rhs: T) -> T? {
Realm() // replace with whatever Realm()-specific stuff you want to do
return lhs+rhs
}
func Realm() {
// ...
print("Called realm")
}
var a = MyType(int: 1, string: "foo")
a.myString === "bar" // calls Realm(). After operation: a.myString = "bar"
a.myInt +== 1 // calls Realm(). After operation: a.myInt = 2
I thought I'd also mention that if you only want to do "Realm stuff" when a value is set (from your example: prior to setting a value, specifically), then the willSet method, used with stored properties, doesn't need to look so messy (nested closures), and personally, I would prefer this method
func Realm() {
print("Called realm")
}
class MyType {
// This isn't so messy, is it?
var myInt : Int = 0 { willSet { priorToSetValue(newValue) } }
var myString : String = "" { willSet { priorToSetValue(newValue) } }
var myDouble : Double = 0.0 { willSet { priorToSetValue(newValue) } }
private func priorToSetValue<T> (myVar: T) {
// replace with whatever Realm()-specific stuff you want to do,
// possibly including doing something with your new value
Realm()
}
init(int: Int, double: Double, string: String) {
myInt = int
myDouble = double
myString = string
}
}
var a = MyType(int: 1, double: 1.0, string: "foo")
a.myString = "bar"
print(a.myString) // calls Realm(). After operation: a.myString = "bar"
a.myInt += 1 // calls Realm(). After operation: a.myInt = 2
Is it possible to get the object type from an optional?
For example, if I have a class that has a property that is an optional string, can I somehow just get back the string type?
The exact use case I have is I have many custom classes all of which have a property that is storing another custom class as an optional value. I would like to write a generic function that will create an instance of the object class stored in the optional.
Here is an example of what I am looking for, although .dynamicType does not work since it is an optional:
class Class1 {
}
class Class2 {
var myOp: Class1?
}
var c = Class2()
c.myOp = c.myOp.dynamicType()
Since you wanted to use this with Generics I tried it for you. It works, but it may not be so useful.
First some setup:
This is a helper protocol to make sure our Generic type will have a known init method.
protocol ZeroParameterInit {
init()
}
This is an extension to get the type from an optional:
extension Optional {
var dynamicWrappedType : Wrapped.Type {
return Wrapped.self
}
}
Implemented in your code:
class Class1 : ZeroParameterInit {
required init() {}
}
class Class2 {
var myOp: Class1?
}
var c = Class2()
c.myOp = c.myOp.dynamicWrappedType.init()
Generic implementation:
class Class1 : ZeroParameterInit {
required init() {}
}
class Class2<T where T : ZeroParameterInit> {
var attribute: Optional<T>// used long syntax to remind you of : Optional<Wrapped>
init(attr:T) {
attribute = attr
attribute = nil
}
}
The function to create the instance:
func myFunc<T>(instance: Class2<T>) -> T {
return instance.attribute.dynamicWrappedType.init()
}
Some tests:
let alpha = Class1()
let beta = Class2(attr: alpha)
beta.attribute = myFunc(beta)
The issue:
You can't create an instance of Class2 without informing it about the type of it's generic attribute. So you need to pass it some object/type and that complicates things again.
Some extra methods that might improve how it all works:
init() {
}
let delta = Class2<Class1>()
delta.attribute = myFunc(delta)
init(type:T.Type) {
}
let epsilon = Class2(type: Class1.self)
epsilon.attribute = myFunc(epsilon)
You just need to check if the optional exist:
func myFunc(c: Class2) -> Class1? {
if let c1 = c.myOp{
return c1.dynamicType()
}
return nil
}
OR
func myFunc(c: Class2) -> Class1? {
if c.myOp != nil{
return c.myOp!.dynamicType()
}
return nil
}
Note the your return type need to be optional as well.
Tried this in simulator, seems like doing the right thing, if I understood you
class Class1 {
}
class Class2 {
var myOp: Class1?
}
func myFunc(c: Class2) -> AnyObject {
if let c1 = c.myOp{
return c1.self
}
return c
}
var object = Class2()
object.myOp = Class1()
myFunc(object) // Class1
just a quick question. I have the following code, which works just fine:
class obA: Printable {
var description: String { get { return "obA" } }
}
class obB: Printable {
var description: String { get { return "obB" } }
}
func giveObject() -> obA { return obA() }
func giveObject() -> obB { return obB() }
var a: obA = giveObject()
var b: obB = giveObject()
println(a)
println(b)
The right variant of giveObject is being called and all is well. Of course this is just a simplified case, in reality in my project there are several dozens of overloads of 'giveObject', all differing in return type. Now, I want to make a generic function to parse all these things. So, next step:
func giveGeneric<T>() -> T {
return giveObject()
}
var c: obA = giveGeneric()
println(c)
And this complains about ambiguous use of giveObject. I can understand where the error comes from, but I don't see right away how I can solve it and use a construct like this...
First of all just a note.
If the generic type of giveGeneric is simply T, then it can be anything (a String, an Int, ...). So how should giveObject() react in this case?
I mean, if you write:
let word : String = giveGeneric()
internally your generic function calls something like:
let result : String = giveObject() // Ambiguous use of giveObject
My solution
I declared a protocol as follow:
protocol MyObject {
init()
}
Then I made your 2 classes conform to the protocol
class obA: Printable, MyObject {
var description: String { get { return "obA" } }
required init() {}
}
class obB: Printable, MyObject {
var description: String { get { return "obB" } }
required init() {}
}
Finally I can write this
func giveGeneric<T:MyObject>() -> T {
return T()
}
Now I can use it:
let a1 : obA = giveGeneric()
let b1 : obB = giveGeneric()
You decide if this is the solution you were looking for or simply a workaround.
That cannot work, even if you implement a giveObject function for any possible type. Since T can be any type, the giveGeneric method cannot determine the correct overload to invoke.
The only way I can think of is by creating a huge swift with as many cases as the number of types you want to handle:
func giveGeneric<T>() -> T? {
switch "\(T.self)" {
case "\(obA.self)":
return giveObject() as obA as? T
case "\(obB.self)":
return giveObject() as obB as? T
default:
return .None
}
}
But I don't think I would use such a solution even with a gun pointed at my head - it's really ugly.
If in all your cases you create instances using a parameterless constructor, then you might create a protocol and constraint the T generic type to implement it:
protocol Instantiable {
init()
}
func giveGeneric<T: Instantiable>() -> T {
return T()
}
You can use with built-in as well as new types - for instance:
extension String : Instantiable {
// `String` already implements `init()`, so nothing to add here
}
let s: String = giveGeneric()
Alternatively, if you prefer you can make the protocol declare a static giveObject method rather than a parameterless constructor:
protocol Instantiable {
static func giveObject() -> Self
}
func giveGeneric<T: Instantiable>() -> T {
return T.giveObject()
}
extension String : Instantiable {
static func giveObject() -> String {
return String()
}
}
let s: String = giveGeneric()