class MyRequest(requests.Request):
def get(self): do_something_stupid()
then my coworkers can still use `requests.Request` itself without getting my bad behavior, and if they find themselves looking at a flaw in my code, they know not to blame the upstream author. What's different about the Swift situation?I'm kind of horrified at the idea of an OOP language that wouldn't easily let me override a parent class's behavior. If I break something in the subclass, it's on me to fix it. That never reflects poorly on that parent class.
For example, perhaps right now the function looks like this:
def get(self, url, method='GET'):
...
def post(self, url):
self.get(url, method='POST')
You override get, to add some additional functionality. All is fine.Then somebody realizes that the original code was silly, and rewrites it:
def get(self, url, method='GET'):
if method != 'GET':
print "DEPRECATED!"
self.request(url, method=method)
def post(self, url):
self.request(url, method='POST')
It seems to do the same thing, and probably passes all the same tests. But suddenly, now your code doesn't get called for post requests and your additional functionality breaks in a mysterious way.Perhaps its still your fault for doing a bad job subclassing, but its going to look like its the fault of the person who fixed the parent class.
The same exact thing happens when using composition.
The end result is still a broken app (just due to a different reason), and the user will blame either the third party programmer or Apple, and mostly usually the programmer.
Which is to say, there's a good argument for the idea that reducing the ability to monkey-patch framework classes will make it much easier to actually fix bugs in the frameworks.
That was a problem for Microsoft, Apple, from all we publicly know from their releases, never treated that as a problem. They went ahead with the fixes even if it broke previous workarounds.
Also, part of the reason that it takes them long to fix certain bugs may be concerns about seemingly internal changes breaking applications. They cannot refactor methods (rename or even change an argument list) in any class they ship because someone, somewhere, might override one of its methods.
In that light, I think the change makes sense. Of course, Apple could just add private/sealed to all their classes, if only just before shipping, but why make the typical choice more work to write than the exception?
The user just knows said program doesn't work. And it's not necessary that an OS upgrade will break lots of programs that a user has, it can break this or that program in subtle ways, or classes of programs (e.g. those using the X api) of which a typical user will have only few installed.
E.g. if it breaks third-party camera apps, users might not normally have 5 of those, to see that they all break at the same time, but just 1 additional on top of Apple's (if that).
Especially since, with the ability for apps to upgrade automatically, many don't even keep track when this or that app was updated.
Of course it usually is even more obscure, e.g. the bug only affects PART of the app's functionality, a part which you might have not invoked in your last run before the OS update. So, another deduction for many would be that that feature works intermittently because it's not coded well, etc.
Besides, even when the user can deduce that the OS broke the app, they don't complain to Apple, but to the software maker "fix your app", "where's the update release?", etc.
Apple writes a new API. It has a problem. You try to adopt it, it doesn't work. You don't just ship that, you do something else.
Unpleasant, but doesn't hit the user.
So the problem remains: you can't easily extend the class with your own fix to bring out a bugfix release for your app.
But if you're working in a team (or contributing a patch to a Github project), and you override something crutial like String.subtring(), then things could get out of hand.
IIRC, this was an interview question at Google when I applied in 2008, and I think one of the reasons I got the job was because I was aware of all of the pitfalls of it.
I managed to skip using underscore, but from a quick glance through the library, isn't the reason it's called underscore because it provides '_' as a namespace for all the utility functions, rather than altering Array.prototype the way Prototype did?
When you're coding against a closed-source, external, 3rd party platform, being dynamic is really helpful.
Simple as that, IMO.
(From a distance, Swift sure does have a strong C++ vibe.)
The rhetoric on both sides can quickly get stupid. This is one of the major ways in which languages are divided. Ruby folks are used to being able to monkey patch everything, and Python folks tend to avoid it even though they can. JavaScript programmers are divided on the issue: should you add a method to Array.prototype, or is that just asking for trouble? I've certainly seen my own fair share of bugs and crashes caused by programmers substituting types where they shouldn't, and seen my fair share of frustrating limitations in sealed modules that should just expose that one method I need, dammit.
Objective-C leaned towards the "go wild, do anything" approach, which grew quite naturally out of the minimalistic "opaque pointer + method table" foundations for object instances. One of the reasons that you make such a choice in the first place is the ease of implementation, but in 2015, writing your own compiler is easier than ever. So Apple is quite naturally considering application reliability as a priority (since they're competing with a platform that uses a safer language for most development).
Unfortunately, it's a cultural fight where one side or the other must necessarily lose.