Programming languages have very few differentiated constructs. They calcify common patterns. The while loop tames the goto, fixing the if-then-goto pattern. While while is the human use of goto, foreach is the human use of variables. Foreach sees the possibility of writing the same code and, by changing the values, applying it to a number of variables. These two take a latent possibility and turns it into a pattern which is comprehendible to reduce the amount of code written. What others are there?
Numbers are quantities. Algebra abstracts away from numbers: variables carry pointers to numbers. Code abstracts once more: variables carry pointers to code, that which can be run to produce more code, or more pointers, or more numbers. What's the next level?
It's no use asking what an object is, you have to ask what it does. The code cannot guarantee the data has total integrity unless the data store and the code comprise a self-contained, unbreakable system (they never do). Asking what the object is an instance of is prone to breakage. Use duck typing. Assume the minimum about the data of the object for any given operation. Try it. If it doesn't work, that's fine. Do more if there's more data present. Operate by binding, not by pointing. Data lookups are different with binding: you need to express not a type, but a possibility, and ask the datastore what could work with that. Limits are set by inflection points of possibilities of binding, not by categorisation by properties. A flirting glance for code; a runtime implicature.