10 ms·
> The article describes how the Linux kernel, despite being written in C, embraces object-oriented principles by using function pointers in structures to achiev
by ryao 1y ago
> The article describes how the Linux kernel, despite being written in C, embraces object-oriented principles by using function pointers in structures to achieve polymorphism.
This technique predates object oriented programming. It is called an abstract data type or data abstraction. A key difference between data abstraction and object oriented programming is that you can leave functions unimplemented in your abstract data type while OOP requires that the functions always be implemented.
The sanest way to have optional functions in object oriented programming that occurs to me would be to have an additional class for each optional function and inherit each one you implement alongside your base class via multiple inheritance. Then you would need to check at runtime whether the object is an instance of the additional class before using an optional function. With an abstract data type, you would just be do a simple NULL check to see if the function pointer is present before using it.
- mistrial9 1y agoThe concept of abstract data type is a real idea in the days of compiler design. You might as well say "compiler design predates object oriented programming". The technique described in the lead is used to implement object-oriented programming structures, just as it says. So are lots of compiler design features under the hood. source- I wrote a windowing framework for MacOS using this pattern and others, in C with MetroWerks at the time.
- ryao 1y agoCompiler design does predate object oriented programming. The first compiler was made by John Backus et al at IBM in April 1957. As for abstract data types, they originated in Lisp, which also predates object oriented programming.
- pjmlp 1y agoActually, no. "AN ALGORITHMIC THEORY OF LANGUAGE", 1962 https://apps.dtic.mil/sti/tr/pdf/AD0296998.pdf https://apps.dtic.mil/sti/tr/pdf/AD0296998.pdf In this paper they are known as plexes, eventually ML and CLU will show similar approaches as well. Only much latter would Lisps evolve from plain lists and cons cells.
- ryao 1y agoYou caused me to do some digging. That publication is dated November 1962. The Lisp 1.5 manual’s preface is dated August 17, 1962, which is even older. It describes lambdas and property lists, which seem like they can be used to implement ADTs, although I do not have a Lisp 1.5 interpreter since those are obsolete, so I cannot verify that. Computer history articles claim that Simula, the first object oriented language, was born in May 1962, but was not actually operational until January 1965: https://history-computer.com/software/simula-guide/ https://history-computer.com/software/simula-guide/ Thus, while I had thought Lisp had ADT concepts before the first OOL existed, now I am not sure. My remark that they originated in Lisp had been said with the intention that I was talking about the first language to have it. The idea that the concept had been described outside of an actual language is tangential to what I had intended to say, which is news to me. Thanks for the link.
- hiker 1y agoPlexes are first mentioned in 1960 https://dl.acm.org/doi/pdf/10.1145/366199.366256 https://dl.acm.org/doi/pdf/10.1145/366199.366256 and the paper even starts with a critique of the efficiency of Lisp's approach for representing data with cons pairs (citing McCarthy's paper from the same year). You might also want to watch Casey's great talk on the history of OOP https://www.youtube.com/watch?v=wo84LFzx5nI https://www.youtube.com/watch?v=wo84LFzx5nI
- pavlov 1y agoIn Smalltalk and Objective-C, you just check at runtime whether an object instance responds to a message. This is the original OOP way. It's sad that OOP was corrupted by the excessively class-centric C++ and Java design patterns.
- mettamage 1y agoWait, so in obj-c, could you also write some kijdnof doesnotunderstand method to achieve some dynamic method dispatch?
- pjmlp 1y agoYes, that is how microservices were implemented in the days of NeXTSTEP. with PDO. https://en.wikipedia.org/wiki/Portable_Distributed_Objects https://en.wikipedia.org/wiki/Portable_Distributed_Objects
- mettamage 1y agoSo why did Swift become a thing? Or does Swift has this too?
- bitwize 1y agoBecause Objective-C does not have foo.bar() style method calls and that's what everybody else uses and wants.
- saagarjha 1y agoBecause Swift adds many other features.
- astrange 1y agoSwift isn't messaging-based, it's protocol-based. (Except it's also messaging-based if you use @objc.)
- pjmlp 1y agoBecause Objective-C being based on C, means it would never be safe while remaining compatible with C. Also dynamic runtime dispatch Smalltalk style can never be as fast as the VMT based dispatch, or compile time dispatch via generics, even with all the optimizations in place, that objc_msgSend() has had during its lifetime. Still, Metal is implemented in Objective-C, so there is that.
- 1718627440 1y ago> This technique predates object oriented programming. I would rather say that OOP is a formalization of predating patterns and paradigma.
- ryao 1y agoOOP cannot be a formalization of what predated it because the predating patterns support things that OOP explicitly disallows, like instantiation with unimplemented functions. That is extremely useful when you want to implement an optional function, or mutually exclusive functions such that you pick which is optional. This should be the case in the Linux VFS with ->read() and ->read_iter(). Also, ASTs were formalized after OOP, despite existing prior to it in Lisp. For full disclosure, I have never verified that leaving ->read() unimplemented when ->read_iter() is implemented is safe, but I have seen enough examples of code that I strongly suspect it is and if it is not, it is probably a bug.
- 1718627440 1y ago> like instantiation with unimplemented functions I think this is more of an effect of C distinguishing between allocating memory (aka object creation) and initialization, which other languages disallow for other reasons, not because there are not OOPy enough.
- p_l 1y agoOOP does not disallow instantiation with unimplemented functions, it's just an artefact of implementation in some languages.
- yndoendo 1y agoInheritance is not needed when a composite pattern can be used. class DefaultTask { } class SpecialTask { } class UsedItem { UsedItem() { _task = new SpecialTask() } void DoIt() { _task.DoIt() } } Is python a OOP language? Self / this / object pointer has to be passed similar to using C style object-oriented / data abstraction.
- 1718627440 1y agoThe interesting thing is, that in the OOP implementation inheritance IS composition of vtables and data. It's really only syntactic sugar, that is sometimes not unambiguous.
- zozbot234 1y agoThis is not quite correct. OOP implementation inheritance involves a kind of "open recursion" (that is, calls to base-class methods can end up dispatching to implementations from a derived class) that is not replicated with pure composition. All method calls, including method calls that originate from code in some class anywhere in the hierarchy, ultimately dispatch through the vtable of whatever object they're called on.
- 1718627440 1y agoBut that's exactly the same you would need to implement manually when you use composition. When constructing, you also need to construct the contained objects, when doing something that should affect a contained object, you need to dispatch it. When a method is never overridden, it doesn't need to be in the vtable.
- zozbot234 1y agoThat's not what people usually mean by "composition" though. The whole point of "use composition over inheritance" is to avoid that behavior.
- 1y ago
- kerblang 1y agoYou can do exactly what was done in C with most OOP languages like Java & C# because you have lambdas now, and lambdas are just function pointers. You can literally assign them to instance variables (or static variables). (sorry it took more than a decade for Java to catch up and Sun Microsystems originally sued Microsoft for trying to add lambdas to java way back when, and even wrote a white paper insisting that anonymous inner classes are a perfectly good substitute - stop laughing)
- Shorel 1y agoAn abstract data type is a software design pattern. The difference is that design patterns are a technique where you use features not implemented by the compiler or language, and all the checks have to be done by the developer, manually. Thus, you are doing part of the work of the compiler. In assembler, a function call is a design pattern.
- trws 1y agoI largely agree, and use these patterns in C, but you’re neglecting the usual approach of having a default or stub implementation in the base for classic OOP. There’s also the option of using interfaces in more modern OOP or concept-style languages where you can cast to an interface type to only require the subset of the API you actually need to call. Go is a good example of this, in fact doing the lookup at runtime from effectively a table of function pointers like this.
- ryao 1y agoMy point is that this pattern is not object oriented programming. As for a default behavior with it, you usually would do that by either always adding the default pointer when creating the structure or calling the default whenever the pointer is NULL. In the Linux VFS for example, there are optimized functions for reading and writing, but if those are not implemented, a fallback to unoptimized functions is done at the call sites. Both sets are function pointers and you only need to implement one if I recall correctly.
- f1shy 1y agoTo be fair, OOP is not 100% absolutely perfectly defined. Strustrup swears C++ is OOP, Alan Key, at least at some point laughed at C++, and people using CLOS have yet another definition
- pjmlp 1y agoYou forgot about people using BETA, or Self, or ......
- naasking 1y ago> My point is that this pattern is not object oriented programming. I think the "is/is not" question is not so clear. If you think of "is" as a whether there's a homomorphism, then it makes sense to say that it is OOP, but it can qualify as being something else too, ie. it's not an exclusionary relationaship.