News for hackers. Stuff that matters.
Re:Why Arc Isn't Especially Object-Oriented (2002) by pka on Saturday October 20, 2018 @07:02PM (#18265940)
Use 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.

Re:Why Arc Isn't Especially Object-Oriented (2002) by wvenable on Saturday October 20, 2018 @08:19PM (#18266183)
As the other commenter pointed out, this seems pretty isomorphic to virtual methods.
Re:Why Arc Isn't Especially Object-Oriented (2002) by pka on Saturday October 20, 2018 @08:29PM (#18266213)
Two 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.

Re:Why Arc Isn't Especially Object-Oriented (2002) by wvenable on Saturday October 20, 2018 @08:56PM (#18266271)
#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.