In Java (and JS) there's a separate, all-knowing garbage collector, while swift is reference counted. In an ARC runtime, the didSet/willSet distinction avoids explicit calls to release the object, which is pretty clearly a good thing on the programmer's end. You can debate whether the benefits of full garbage collectors outweigh their performance characteristics, but given ARC, the didSet/willSet distinction definitely makes sense.
In this scenario it's easy to make the old method do something sensible like "return the first item." But maintaining an old field is more difficult: you can't make it lazy, you can't eliminate its backing storage, etc.
Scala does this quite transparent. Something defined as a `var` (variable), `val` (immutable variable), `lazy val` (lazy immutable variable) or `def` (method) is called source- and binary compatible from the caller side.
I've never seen this trick anyone, except for maybe unexpected bad performance.
I think that Java got this one right. (I do not at all like the cargo cult custom of getter/setter methods for fields; I'm referring to the language only.)