But seriously though, CLOS and Smalltalk-style OOP is probably the only flavor of OOP I really enjoy to use, and Objective-C gets you way closer to that than C++ and Java do. (e.g. the way KVO is implemented relies on "isa-swizzling", or dynamically changing classes at runtime)
Even JavaEE was initially born as a Objective-C framework, Distributed Objects Everywhere.
The only app I'm currently maintaining and proud of[1] makes tons of use of "traditional" OOP. It uses lambdas and FP when necessary. I think it makes absolutely no use of JavaScript's dynamic features. I'm fairly sure this code would port easily to ObjC.
After 15-20 years, you just get bored of doing things in novel or "pure" ways, and do the bare minimum needed to get the job done that's in front of you.
Maybe saying "flavor of OOP" was too vague, but I am talking about implementations of object systems, not the (ill-defined) notion of OOP.
Using your analogy with hammers and screwdrivers, my post is less "I prefer screwdrivers over hammers" and more "I prefer screwdrivers with bit holders over screwdrivers without bit holders"
I relished the day Swift was announced, and have been using it ever since.
Once I had all the convenience guts in place, writing actual functionality has been a delight though (outside of the overly-verbose let/guard and type casting)
That said, I'm pretty sure I'm also probably just hard headed and doing it wrong, and could've learned the accepted patterns/methodologies lol
Headers are a feature, not a bug. They're the API. They help document the API and also keep it separate from the implementation.
Xcode presents the equivalent of a “header” when you follow a symbol to a framework you don’t have the source for… it’s a swift file full of definitions only and no implementations. The compiler emits this for you automatically as a .swiftinterface file
> or keep things non-`public`
I definitely am a swift developer that would complain about this. It’s way too easy to be cavalier about using the “public” keyword and making things part of the public API when they probably shouldn’t be. It’s like engineers have muscle memory from Java and just type “public class” without really questioning why first.
It's so incredibly slow, though, which is frustrating. It would be ok if only this were as instantaneous as checking a header file.
Ironically, almost everything about "Swift" is slower than Objective-C.
That problem was already solved with header files; trivial to split interface from implementation, they’re just two different files. But sometime around the 90s, probably Java and this was deemed inconvenient. Now we’re trying to reinvent that same pattern
This is a good pattern for some cases, like the public members of a package. However, I love that I don’t need to do this for every class I write.
And if you do use this approach, at least swift will emit a compile error if your protocol and implementation signatures don’t match.
ObjC will happily compile if your header is missing an implementation and crash at runtime.
Headers are such an idiotic design, over-abstraction harms locality of reasoning.
Why parse out a whole C file when you can get the only bits that matter for compiling your file from a 30 line header?
My other complaint with it compared to Swift is how one needs to pull in a bunch of utility libraries to do many things that come stock with Swift.
It’s less verbose (even if I’m not a square bracket hater. It has some really nice new abilities like async (way easier/cleaner than callbacks in many situations) and now actors.
But honestly 90% of it is true type safety. The type system is so much more powerful and expressive compared to Obj-C.
There is only one downside, and it’s real. Compiling Obj-C was instantaneous. Swift is MUCH slower, which also slows down error messages and hints. And the fancy type stuff can even timeout the compiler.
Combined with some Xcode issues (stale info anybody?) and it can be a pain.
But I’m happy we have Swift.
Objective-C does just about everything it can to make sure you can mess with it at runtime and confuse the ever living hell out of any type checker that wants to be strict.
And the additional strictness is one of my favorite parts of Swift.
Of course, C has a lot of ugly traps which makes it less than ideal for this domain. This hypothetical subset language addresses those issues. While, again, you would only reach for the 'Objective' parts when your code benefits from being object oriented.
It is true that the inherit dynamism of message passing makes static analysis impossible to cover all cases, but as with all things in life there are tradeoffs. You lose the nice aspects of object oriented systems if you do not allow for that, and OO is particularly well suited to UI code.
Of course, Swift abandoned the object oriented model completely. Which is fine. But Objective-C showed that you can have your cake an eat it too, offering OO where appropriate, and a non-OO language for everything else.
Objective-C's downfall was really just in that C didn't age well – which, among other things, I am sure contributed to seeing the use of the 'Objective' bits where they weren't really appropriate.
Classes, interfaces,interface and class inheritance, polyphormism, variance, type extensions, compile time and dynamic dispatch, overloading, associated types.
Is there some value in this logically flawed correspondence that I have overlooked? What is it trying to add?
Where both languages are poor is how large the binaries they produce are.
Possibly in ways that are very inconvenient/hard to use in Obj-C.