4 ms·
That's exactly what I hate about Cocoa. Sure Carbon wasn't perfect, but subclassing NSTableView so that you can inject your subclassed NSTableHeaderView just to
by sdegutis 8y ago
That's exactly what I hate about Cocoa. Sure Carbon wasn't perfect, but subclassing NSTableView so that you can inject your subclassed NSTableHeaderView just to make some UI tweaks is awful. The entire framework is like this, and Swift doesn't help much. I get that it's a legacy design due to performance issues back from when Cocoa was created 25 years ago, but I would absolutely love to see a modernized macOS UI framework where functions were always used in place of delegates or subclassing, and where lexical scoping is the backbone of your app's own internal architecture instead of class hierarchies.
- wvenable 8y ago> functions were always used in place of delegates or subclassing I'm not sure what this means? In your modernized UI framework, how would you want to be able to make UI tweaks to built in OS/framework components? I've seen a few other system for customization and they all tended to be worse than just being able to subclass internal classes and override methods. Now I admit this can be terribly brittle but often the alternative is no way to customize at all.
- aaaaaaaaaab 8y agoI guess instead of overriding methods like “windowDidLoad”, you would set a function (I mean block) as “window.loadHandler” or something like that. I don’t really see why this would be better, to me the two approaches seem isomorphic...
- pka 8y agoUse higher order functions to customise behaviour. I.e. your hypothetical NSTableView would look like this: nsTableView :: { renderCell :: a -> NSView -- this is the function that renders a cell given an `a` , header :: NSView , footer :: NSView } -> [a] -> NSTableView a I.e. pass in a function that renders a cell for a given `a`, a header and a footer NSView and whatever else, a list of `a`s and get back a NSTableView which displays that list of `a`s. React calls this pattern higher order components iirc.
- wvenable 8y agoAs the other commenter pointed out, this seems pretty isomorphic to virtual methods.
- pka 8y agoTwo obvious differences off the top of my head: 1. Overriden methods have access to the internal state of the parent class, which is almost universally a bad idea. 2. Since functions are values, you can freely mix and match different view configurations without having to create a subclass for every permutation.
- wvenable 8y ago#1 isn't true; you only have access to the state that subclasses are allowed to have (assuming you're using a language with any protection at all). #2 is a good point. But there are some limitations as well. You don't get to augment the default implementation unless it is also exposed somewhere (passed into the function). Both methods have a lot in common with the obvious differences that you mention. A class with no public methods and a empty virtual function is equivalent to a class calling a higher order function in the same place. If that virtual function has a implementation, you can get the same functionality with a higher order function by passing in the base implementation as a parameter. For full equivalence, you could also pass the object instance as well. Add in protected methods and/or state and you can get that with a second class that implements an internal API and again pass that to the higher-order function. Ultimately you can achieve all kinds of equivalence this way. I think there is some advantage to using the terminology in the language (private, protected, virtual, abstract, this/base, etc) to describe the more complex situations. Having a simple function call is useful for more simple situations. This is the classic struggle.