Getting rid of willSet/didSet


(Tino) #1

Hi there!

Considering that I just read that someone wants to have „willGet“, I guess willSet and didSet are here to stay — but for me, the concept has several downsides:
- two special keywords
- oldValue as another special word (there are some of those, but afaics only self and super are used often)
- imho it is not intuitive in which order those methods are called when subclassing
… and all those special rules only work for properties.

I think NS_REQUIRES_SUPER (beside the hard name) is much better, because
- it works for every method (I guess everyone knows some classes in Cocoa where the docs say you must call super, but the compiler cannot enforce this)
- order of execution is clear
- it is easy to block a change, instead of doing a rollback in „didSet“

The only advantage of willSet/didSet is that it is easy to create a stored property and be notified when it is changed, without the need to create an additional field — but I think it wouldn’t be that bad to just write „super.property = value“, even if there is no superclass as backing store: It may appear odd, but shouldn’t cause any problems.

Best regards,
Tino


(Andrey Tarantsov) #2

The only advantage of willSet/didSet is that it is easy to create a stored property and be notified when it is changed, without the need to create an additional field — but I think it wouldn’t be that bad to just write „super.property = value“, even if there is no superclass as backing store: It may appear odd, but shouldn’t cause any problems.

It *is* odd, and I do the described didSet trick *all* the time.

Stuff like:

public class MyView: UIView {

  public var foo: Int {
    didSet {
      setNeedsDisplay()
    }
  }

  // ... ditto for 10 more properties ...

}

I would not appreciate that code getting any longer. It's such a relief after what I had to write in Objective-C!

A.


(Tino) #3

It *is* odd, and I do the described didSet trick *all* the time.

Stuff like:

The alternative wouldn’t be that complicated:

public class MyView: UIView {
  public var foo: Int {
    set(value) {
      super.foo = value
      setNeedsDisplay()
    }
  }
}

It’s just one line more, but three(!) keywords less that could be removed from the language; and I bet in the wild there are many thousand errors in subclasses of UIViewController that happen because the author didn’t remember wether he has to call super in viewDid…, loadView etc.


(Jack Lawrence) #4

I’m not sure I understand your example. `super` is a reference to the superclass implementation of `foo`, but `UIView` doesn’t declare a property called `foo`.

Jack

···

On Dec 14, 2015, at 11:23 PM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

It *is* odd, and I do the described didSet trick *all* the time.

Stuff like:

The alternative wouldn’t be that complicated:

public class MyView: UIView {
  public var foo: Int {
    set(value) {
      super.foo = value
      setNeedsDisplay()
    }
  }
}

It’s just one line more, but three(!) keywords less that could be removed from the language; and I bet in the wild there are many thousand errors in subclasses of UIViewController that happen because the author didn’t remember wether he has to call super in viewDid…, loadView etc.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Nicky Gerritsen) #5

But how does this work if `super` does not have `foo`, exactly like in this example? UIView does not have a member named `foo`, so it will not work.
Moreover, currently if creating a setter, you also need to supply a getter.

Regards,

Nicky

···

On 12/15/2015 08:23 AM, Tino Heth via swift-evolution wrote:

It *is* odd, and I do the described didSet trick *all* the time.

Stuff like:

The alternative wouldn’t be that complicated:

public class MyView: UIView {
  public var foo: Int {
    set(value) {
      super.foo = value
      setNeedsDisplay()
    }
  }
}

It’s just one line more, but three(!) keywords less that could be removed from the language; and I bet in the wild there are many thousand errors in subclasses of UIViewController that happen because the author didn’t remember wether he has to call super in viewDid…, loadView etc.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Charles Srstka) #6

-1 on this. As others have mentioned, willSet and didSet are extremely useful, and the above is a misuse of “super”, misleading the reader to suppose that UIView implements “foo”, when it does not.

Charles

···

On Dec 15, 2015, at 1:23 AM, Tino Heth via swift-evolution <swift-evolution@swift.org> wrote:

It *is* odd, and I do the described didSet trick *all* the time.

Stuff like:

The alternative wouldn’t be that complicated:

public class MyView: UIView {
  public var foo: Int {
    set(value) {
      super.foo = value
      setNeedsDisplay()
    }
  }
}

It’s just one line more, but three(!) keywords less that could be removed from the language; and I bet in the wild there are many thousand errors in subclasses of UIViewController that happen because the author didn’t remember wether he has to call super in viewDid…, loadView etc.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tino) #7

I’m not sure I understand your example. `super` is a reference to the superclass implementation of `foo`, but `UIView` doesn’t declare a property called `foo`.

It’s quite simple: „super“ is just a string that can have a special meaning for the tokenizer, and normally, we read it as „please do what the class I’m inheriting from would do“ — but you could as well interpret it as „do what would happen if my implementation didn’t exist“, which has a slightly wider scope.

In the old dark ages, when properties with todays comfort didn’t exist, the only thing we could do was declare a pair of methods to read and write a field. Those are boring, but under the hood, they are still there, lurking in a dark thin layer in the hierarchy of inheritance.
Of course, the method that actually copies the bytes of class Bs instance variable „foo“ doesn’t belong to Bs parent A, so with the narrow interpretation of super, there is no way to utilize the nifty helper method that is created for us: When we write our custom accessor for foo, it is overwritten, and there is no path to reach it… unless we add our setter in subclass C, where Bs syntax problem disappears, and „super.foo“ connects us to those helper methods.

The alternative to subclassing is creating a backing field, just like old Objective-C did, and even a young language like Kotlin has something similar (afaik it is more secure, and $foo only exists in foos accessor). Swift, on the other hand, shirks the problem by introducing of a whole set of new keywords that aren’t useful anywhere else.

Guess I should have started this small discussion coming from the other direction: Seems I just created refusal by „attacking“ a tiny useful feature, instead of writing about the benefits that NS_REQUIRES_SUPER has to offer in the first place, and reach the conclusion that it can make existing constructs obsolete when everyone is thrilled about the potential advantages… so, maybe we could forget about the subject of this message and argue about the pros and cons of that cool attribute? :wink:


(Adrian Kashivskyy) #8

I'm -1 on that, willSet and didSet are great tools for performing side effects (such as locking, for example). It was a major problem in Objective-C, as no easy solution (except overriding accessors) existed and still you'd have to write a lot of boilerplate code.

Pozdrawiam – Regards,
Adrian Kashivskyy

···

Wiadomość napisana przez Nicky Gerritsen via swift-evolution <swift-evolution@swift.org> w dniu 15.12.2015, o godz. 08:50:

But how does this work if `super` does not have `foo`, exactly like in this example? UIView does not have a member named `foo`, so it will not work.
Moreover, currently if creating a setter, you also need to supply a getter.

Regards,

Nicky

On 12/15/2015 08:23 AM, Tino Heth via swift-evolution wrote:

It *is* odd, and I do the described didSet trick *all* the time.

Stuff like:

The alternative wouldn’t be that complicated:

public class MyView: UIView {
  public var foo: Int {
    set(value) {
      super.foo = value
      setNeedsDisplay()
    }
  }
}

It’s just one line more, but three(!) keywords less that could be removed from the language; and I bet in the wild there are many thousand errors in subclasses of UIViewController that happen because the author didn’t remember wether he has to call super in viewDid…, loadView etc.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Colin Cornaby) #9

I think the below proposal also tries to pave over the difference between will and didSet, which are both important. In addition to unclear use of super.foo.

···

On Dec 15, 2015, at 12:57 AM, Adrian Kashivskyy via swift-evolution <swift-evolution@swift.org> wrote:

I'm -1 on that, willSet and didSet are great tools for performing side effects (such as locking, for example). It was a major problem in Objective-C, as no easy solution (except overriding accessors) existed and still you'd have to write a lot of boilerplate code.

Pozdrawiam – Regards,
Adrian Kashivskyy

Wiadomość napisana przez Nicky Gerritsen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> w dniu 15.12.2015, o godz. 08:50:

But how does this work if `super` does not have `foo`, exactly like in this example? UIView does not have a member named `foo`, so it will not work.
Moreover, currently if creating a setter, you also need to supply a getter.

Regards,

Nicky

On 12/15/2015 08:23 AM, Tino Heth via swift-evolution wrote:

It *is* odd, and I do the described didSet trick *all* the time.

Stuff like:

The alternative wouldn’t be that complicated:

public class MyView: UIView {
  public var foo: Int {
    set(value) {
      super.foo = value
      setNeedsDisplay()
    }
  }
}

It’s just one line more, but three(!) keywords less that could be removed from the language; and I bet in the wild there are many thousand errors in subclasses of UIViewController that happen because the author didn’t remember wether he has to call super in viewDid…, loadView etc.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution