Live data from Hacker News

Object-oriented design patterns in C and kernel development

oshub.org

61–70 of 224 posts

Re: Object-oriented design patterns in C and kernel development

#61
post #2

> 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 abstrac…

> This technique predates object oriented programming. I would rather say that OOP is a formalization of predating patterns and paradigma.

OOP 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.

Re: Object-oriented design patterns in C and kernel development

#62
post #2

> 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 abstrac…

You 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)

Re: Object-oriented design patterns in C and kernel development

#63

Earlier quoted context omitted.

Inheritance 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.

Python doesn't require self to be passed. You need it in method definitions, but not calls.

But you can do it. Actually you can call instance methods of other classes and change the class of an instance in Python like in C, but this dynamism is probably what makes it slow. Also doing that will make the program quite complicated, more so than in C, since Python also abstracts about this.

Re: Object-oriented design patterns in C and kernel development

#64

Earlier quoted context omitted.

Inheritance 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.

The 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.

This 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.

Re: Object-oriented design patterns in C and kernel development

#65
post #11

Earlier quoted context omitted.

My 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 th…

> My point is that this pattern is not object oriented programming. Isn't this exactly how most (every?) OOP language implements it? You would say a C++ virtual method isn't OOP?

Member function pointers and member functions in C++ are two different things. Member function pointers are not OOP. They are data abstraction.

The entire point of OOP is to make contracts with the compiler that forcibly tie certain things together that are not tied together with data abstraction. Member functions are subject to inheritance and polymorphism. Member function pointers are not. Changing the type of your class will never magically change the contents of a member function pointer, but it will change the constants of a non-virtual member function. A member function will have a this pointer to refer to the class. A member function pointer does not unless you explicitly add one (named something other than this in C++).

Re: Object-oriented design patterns in C and kernel development

#66
post #10

Earlier quoted context omitted.

Wait, so in obj-c, could you also write some kijdnof doesnotunderstand method to achieve some dynamic method dispatch?

Yes, that is how microservices were implemented in the days of NeXTSTEP. with PDO. https://en.wikipedia.org/wiki/Portable_Distributed_Objects

So why did Swift become a thing? Or does Swift has this too?

Re: Object-oriented design patterns in C and kernel development

#67

Earlier quoted context omitted.

When you think of vtables as unique or owned by an object, then these example seem weird to you. When you think of them as orthogonal to your types/objects, these examples can be useful. In the first example, object1 and object2 can very much be of the same type or compatible types/subtypes/supertypes. Having vtables per object as opposed to per class to me indicates, that it IS intended to modify the behaviour of an…

"Orthogonal" vtables are essentially traits/typeclasses.

What I really like about C is that it supports these sophisticated concepts without having explicit support for them. It just naturally emerges from the core concepts. This is what makes it feel like it just doesn't restrict the programmer much.

Maybe it's a bit due to its evolution. It started with a language that should have all features every possible, that was to complicated to be implemented at the time. Then it was dumbed down to a really simple language. And then it evolved along side a project adding the features, that are truly useful.

Re: Object-oriented design patterns in C and kernel development

#68
post #11

Earlier quoted context omitted.

My 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 th…

> 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.

Object oriented programming implies certain contracts that the compiler enforces that are not enforced with data abstraction. Given that object oriented programming and data abstraction two live side by side in C++, we can spot the differences between member functions that have contracts enforced, and members function pointers that do not. Member functions have an implicit this pointer, and in a derived class, can call the base class version via a shorthand notation to the compiler (BaseClass::func() or super()), unless that base class version is a pure virtual function. Member function pointers have no implicit this pointer unless one is explicitly passed. They have no ability to access a base class variant via some shorthand notation to the compiler because the compiler has no contract saying that OOP is being done and there is a base class version of this function. Finally, classes with unimplemented member functions may not be instantiated as objects, while classes with unimplemented member functions pointers may.

If you think of the differences as being OOP implies contracts with the compiler and data abstraction does not (beyond a simple structure saying where the members are in memory), it becomes easier to see the two as different things.

Re: Object-oriented design patterns in C and kernel development

#69
post #34

A few years ago Peterpaul developed a lightweight object-oriented system on top of C that was really pleasant to use[0]. No need to pass in the object explicitly, etc. Doesn't have the greatest documentation, but has a full test suite (e.g., [1][2]). [0] https://github.com/peterpaul/co2 [1] https://github.com/peterpaul/co2/blob/master/carbon/test/pas... [2] https://github.com/peterpaul/co2/blob/master/carbon/test/pas…

For people wondering what it looks like without the syntactic sugar of carbon then look here [0]. As far as I can see, there's no support for parametric polymorphism. 0. https://github.com/peterpaul/co2/tree/master/examples/my-obj...

Doesn't look much different than GLib the base for the GTK implementation (and other things in GNOME, the GNU Network _Object_ Model Environment).

Re: Object-oriented design patterns in C and kernel development

#70
post #61

Earlier quoted context omitted.

> This technique predates object oriented programming. I would rather say that OOP is a formalization of predating patterns and paradigma.

OOP 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…

> 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.

Post reply on HN