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.
I don’t really see why this would be better, to me the two approaches seem isomorphic...
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.
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.
#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.