Yup.
YMMV
Early in the OOP fad phase,
the suggestion that OOP had any very close connection
with real world objects and the idea
described in the OP
as anthropomorphism sent me into nearly a rage
of indignation -- as if I was being force fed
conceptual sewage.
E.g., consider plants, billiard balls, cars,
bottles in a cupboard, etc. with each
represented by
a software object
(that is, an instance of some class) and then
want to program some real world situation for
those real world, physical
objects, say, the first shot in a game
of billiards where the balls bounce off each
other and the rails and fall into pockets, where
planets affect each other via gravity or collide,
where cars move as in traffic, etc.;
then, we ask,
do the programming constructs of OOP really,
naturally, automatically, or even seriously
help handling the billiard ball collisions,
the gravity, the traffic jams? My view was --
not really, at best not much.
Eventually I just decided to regard
OOP as a glass half full and
like what was there that I could like
and f'get about the rest; then I
regarded an instance of
a class as much like what the OP calls
a record or, more accurately, like
a structure in PL/I.
Note: PL/I structures have a
really nice advantage
because all the addressing is just
array addressing -- super nice,
that is, simple and fast, that is,
typically there is little or no
need for the compiled code to
follow pointers to get to
variables in the structure.
Then the
definition of the class was much like
a based structure in PL/I where could
allocate as many instances as desired.
Then for the OOP methods, in PL/I
just have some entry variables in the
structure. The rest of OOP looked like no more
than syntactic convenience (sugar).
Actually, for OOP inheritance,
PL/I had key word LIKE
where could have a structure A
and then define a structure B
and for part of B say it was just
like structure A.
For OOP inheritance and polymorphism,
I was not impressed: So far, in my
own code, I've never used inheritance
if only because there will be
source code dependencies likely a
long way away in the code base --
e.g., might be inheriting from some class
have never seen, which sounds like
programming partly in the dark and risky,
that is, error prone. For polymorphism,
I've used it a few times -- okay, I did
it with interfaces which are essentially
the same as passing an entry variable
in old Fortran.
For encapsulation, sure, I get some of that
when I use some of the classes in the
Microsoft .NET Framework; if I can trust
what Microsoft did, and really I have little
choice, then okay. I have written
a few classes where there is some
encapsulation -- push the low level details
out of sight where I don't have to
work with them or risk using them
wrong and making a mistake.
E.g., have a class that reads a file
and has a method that on each call
returns the next token in the file --
not a biggie.
Two final points:
(1) Simplicity.
Mostly just keep everything as simple as possible
but not simpler. If something is at all complicated,
then write some good documentation to
explain it and show that, still, actually, it
really is simple. With things so simple,
a lot of the tricky stuff in this and that
programming language mostly don't much need.
E.g., a closure sounds a lot like passing
to a function A
an entry variable as an argument to a function B
and where function B
uses some syntactically nested scope of names
to manipulate variables it has access to
merely via scope of names and where the
function A does not. I did that a few times
in PL/I; it's tricky coding, and
I'm not thrilled with it.
(2) Libraries.
The code I write is mostly just mortar or
glue to hold together uses of
functions and methods in classes from
Microsoft, etc.
In my project, at times I've written
some code that has some real conceptual
content, really from some applied math
I derived, but such code has been relatively
short (the code via Microsoft's ASP.NET for
even a relatively simple Web page
can be much longer), and given the applied
math in good form, the code was fast, fun,
easy, and short.
So, I write some challenging code occasionally,
but otherwise I end up writing a lot of
routine mortar or glue code.
So, for me, the programming comes down to
define storage (sometimes with classes),
allocate/free (with the Microsoft managed code
languages mostly can just f'get about free),
assign the value of an expression,
if-then-else, do-while,
call-return, try-catch, and then document it
so that six months later I can still understand it.
Right, the OOP examples with animals, shapes,
and cars I did not regard as significantly
useful or helpful in practice -- much
better is just document the code, that is,
explain it to a human.
YMMV