5 ms·
That's not very convincing. Why can't a "dog" be a perfectly ordinary data structure that you manipulate the usual way? while True: for dog in dogs:
by dTal 5y ago
That's not very convincing. Why can't a "dog" be a perfectly ordinary data structure that you manipulate the usual way?
while True:
for dog in dogs:
if dog["hungry"] == True:
dog["lastfed"] = time()
dog["hungry"] = False
Okay, I hear you say, but the fact that a dog is an associative array is an implementation detail. Supposing I want to abstract that - don't I need objects then? No! Just define some functions:
while True:
for dog in dogs:
if is_hungry(dog) == True:
update_last_fed(dog)
satiate_dog(dog)
So you end up with an abstract type (dog) and a bunch of functions that operate on that abstract type. Is there any advantage to "gluing" the functions to the data? Well yes, but it's subtle. Imagine you had two types of animal:
while True:
for pet in pets:
if species_of(pet) == "dog":
if is_dog_hungry(pet) == True:
update_last_fed_dogfood(pet)
satiate_dog(pet)
elif species_of(pet) == "canary":
if is_canary_hungry(pet)
...etc etc ad nauseam
With objects, you can make this elegant with pet.satiate() etc. Note however that this problem goes away with multiple dispatch - there's no reason why the language couldn't be designed so that satiate(pet) called different functions contingent on the type of pet. We already do this for math! Adding two floats is mechanically distinct from adding two ints, but it's a rare language that makes the programmer use different functions.
- qayxc 5y ago> Is there any advantage to "gluing" the functions to the data? Depends on the capabilities of the language. If the language supports function overloading and type-checking, then no. Otherwise the "fun" begins if you add different variations of the same basic data that require subtle changes for working with them. In the case of Python you'd end up with a manual type-checking pattern and nested if-else statements within the functions. In the OO case you can leverage protocols, composition and (to a lesser extent) inheritance.
- ozim 5y agoIf you don't have any imagination and you treat dogs as database entries then yes you might do just that. If you are only person writing it and using that code, the same. You did not address interaction between dogs. Some other idea, how do you pass dogs to a playpen, how would they interact - maybe you want different playpens where you can send your dogs into, some playpens having food, some not having a food, different types of food. What if some other developer will have to write code to heal the dog? If function to dog.Heal() will be in some different module that you never heard of, how do you find it? You don't want to make each playpen having "if species_of(pet)" code duplication, if pet alone can act on its own will. Writing code in here seems not that useful here because you would really have to imagine possibilities and see how much code would go into wiring up such a world. Then seeing how having methods in object are helping organize code and in the end prevent whole classes of errors. Building all of that as an example is just too much work for one off discussion. Just play with imagination of how much complexity you can add to a simple example and soon you will notice.
- dTal 5y agoWell respectfully, you provided the original project spec as an example of where objects were required, and I demonstrated that no, they mostly weren't. I agree that it's unproductive for you to keep adding things to the spec so that I can demonstrate that nope, you still don't need objects to do all that. All that objects are, are functions glued to data. That's it. Whether or not you choose to glue them together, the behavior of the dog lies in the functions, and the state of the dog lies in the data. Frankly, your examples seem to lead away from objects - how will another developer add the ability to heal dogs, for instance? They can't change the class definition, so they'll have to do something awful like subclass it into HealableDog(), which doesn't interoperate with all the existing dog code at all. Meanwhile, if 'dog' is simply a big ol' struct of data, they can write a function heal(dog) and call it a day. I highly recommend the first part of this video, which explains the composability problems with objects very well - with dogs and cats even! https://www.youtube.com/watch?v=kc9HwsxE1OY https://www.youtube.com/watch?v=kc9HwsxE1OY
- throwaway889900 5y agoMake Dog implement Healable, duh.
- dTal 5y agoThe original author can do that. Another author cannot add that functionality later, as a library. The can only define a new kind of dog.
- throwaway889900 5y agoSubclass Dog into MyDog, which is exactly the same as Dog. From there, use and modify MyDog as though you would be modifying Dog. Any class that references base class Dog isn't modifiable, but any future work you can use MyDog instances to get all the functionality you need (with some ugly casting). There are other solutions as well.
- ozim 5y ago
- nyanpasu64 5y ago> Why can't a "dog" be a perfectly ordinary data structure that you manipulate the usual way? In statically typed languages, it's easier to read data out of a struct with fixed types, than a map[string]any and convert it to the expected type on each access. > So you end up with an abstract type (dog) and a bunch of functions that operate on that abstract type. C has no multiple dispatch and no classes. So libraries based around opaque objects (GTK and ALSA etc.) prefix each function name with its struct name, which is verbose and gets tedious to read or write after a while. Is multiple dispatch possible in a statically typed languages with compile-time nonvirtual function resolution? I haven't looked into it, it might be possible.