Objective-C or C++ for a new game developer?

Member
Posts: 161
Joined: 2005.07
Post: #31
Code:
class Animal {
public:
  Animal() {}
  ~Animal() {}
};
class Dog : public Animal {
public:
  Dog() {}
  ~Dog() {}
  void bark() { printf("!\n"); }
};

int main() {
  Animal * test = new Animal[10];
  ((Dog *) &test[1])->bark();
}

That works fine (notice the type cast to keep static typing intact), although I can't imagine why I'd ever need to do something like that. If I want a base Enemy class and have enemy subclasses that have their own specialized functions, I'd either:

a) Have separate arrays for each enemy type to keep things structured and organized (then I'd already know exactly which functions I'd be allowed to call)
b) Just have each subclass override a generic update() function.

Although, being a C++ programmer, I'm just conditioned to think that way. I like how the language imposes a sense of structure on me, to force me to stay organized. (also completely opinion)
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #32
it works, but its not very Object-Oriented, is it?

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #33
Yes, of course that works fine. What doesn't work fine is this:

Code:
class Animal {
};

class Dog : public Animal {
public:
    void bark();
};

class Seal : public Animal {
public:
    void bark();
};

Animal* gimmeSomethingThatBarks() {
    if (rand() % 2 == 0) {
        return new Dog();
    } else {
        return new Seal();
    }
}

int main(int argc, const char *argv[]) {
    Animal* barkingMad = gimmeSomethingThatBarks();
    // now try to call bark() -- you know it does, but you can't make it.
    return 0;
}

The only way you can do what's in the comment is like this:

Code:
Dog *dog = dynamic_cast<Dog*>(barkingMad);
if (dog != NULL) {
    dog->bark();
} else {
    Seal *seal = dynamic_cast<Seal*>(barkingMad);
    if (seal != NULL) {
        seal->bark();
    }
}

Which entirely destroys the point.
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #34
Well, Animal doesn't necessarily have to bark if you have a reflection library. Course, that comes with all it's own evils.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #35
I've used Qt, which hacks reflection on top of C++. It's vile. If you have to go to that amount of trouble to add a feature which is a central part of any sane language, you're using the wrong language.
Quote this message in a reply
Member
Posts: 161
Joined: 2005.07
Post: #36
unknown Wrote:it works, but its not very Object-Oriented, is it?
It's ironic, I make my code try to replicate Obj-C functionality and you admit it made the code less object-oriented. I rest my case maybe?
Quote this message in a reply
Member
Posts: 161
Joined: 2005.07
Post: #37
OneSadCookie Wrote:Yes, of course that works fine. What doesn't work fine is this:

Code:
<snip>
Again, I can't even begin to imagine why I'd ever design a program like that. That's just horrendous design in my opinion. I'd use separate arrays for each class type to keep things organized, or just have each thing use a specialized update() function (which I personally don't do, but I've seen some people use that).
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #38
Quote:I rest my case maybe?
eh.. no you dont.

The need for templates are another example of why C++ is not OO its just a different paradigm, im not saying that its bad for it though.

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #39
Cocoa uses the ability to send a random message to a random object extensively -- every delegate object, for a start. The fact that a message is a thing in and of itself is also important (eg. for -performSelectorOnMainThread:withObject:waitUntilDoneSmile. These things are crucial to the ease-of-use of Cocoa, and one of the major reasons why Java/Swing or C++/Qt (despite its hacked "equivalents") are nowhere near as nice to use.

Bottom line is, if you don't think this behavior is useful, you haven't done enough object-oriented design work Rasp

It's basically rooted in the confusion between "inheritance of interface" and "inheritance of implementation" that so many languages (C++, Java, etc) have. Languages like Python, Ruby, and to a lesser extent ObjC, that don't make a big fuss about formal interface, handle the issues of building a flexible object-oriented design much better.
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #40
OneSadCookie Wrote:Animals don't bark, so having every animal implement a bark() method just so I can call it on Seals and Dogs is a very bad idea... just think of how many methods that do nothing in 90% of cases will be on the Aninmal class!

Having Dogs, (Cats) and Seals independently bark isn't enough in C++; Animal must bark too.

Well, the point of inheritance is to put the most common "stuff" at the top level, no *everything*, although nothing prevents you from putting empty stubs for methods if you want.

Now, if I were to put a bark() method in my Animal class, then it would be because I expect a good number of them to implement this method, otherwise what would be the point of a function taking an Animal instance and asking it to bark? If I actually want this to be useful, then I'll probably care about whether an animal can or can't bark, and so my function would take an appropriate subclass of Animal, say AnimalThatBarks, from which both Dog & Seal would inherit the bark() method.

Obj-C allows a lot of flexibility in comparison, but at the cost of hard to catch runtime errors, as early versions of both Project Builder and Xcode showed.
Quote this message in a reply
Member
Posts: 161
Joined: 2005.07
Post: #41
OneSadCookie Wrote:Bottom line is, if you don't think this behavior is useful, you haven't done enough object-oriented design work Rasp
Seven years and counting. There are so many ways to solve a problem that I doubt said functionality will ever be *required*.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #42
PowerMacX Wrote:If I actually want this to be useful, then I'll probably care about whether an animal can or can't bark, and so my function would take an appropriate subclass of Animal, say AnimalThatBarks, from which both Dog & Seal would inherit the bark() method.

Which is fine as long as you are responsible for all the code...

Early versions of Java suffered from this. A good number of classes implemented a "boolean compareTo(Object other)" method, but there was no base class or interface that declared this method. That meant that whilst it would make sense to write a function like "static void sort(ObjectThatImplementsCompareTo[] array)", the only way you could actually do that was to make your sort method take an Object[] and call compareTo via reflection. Ick. (Later versions of Java added a Comparable interface and retroactively made all classes that had a compareTo method implement Comparable).

You may also hit an issue like this when dealing with third-party code -- imagine you're writing an audio app, and purchase an MP3SoundPlayer class from vendor A, and an AACSoundPlayer class from vendor B. Both have a play() method, but since they don't share a common ancestor which does, you have to wrap both classes up before using them, if you want to treat them uniformly.
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #43
Curious if anyone knows:
Is there an easy way to do abstract classes and methods (ala Java) in Objective-C? I know I can make hard/soft protocols but I'm more interested in the ability to implement most of a class and then leave the details to subclasses (and also barring instantiation).

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #44
The ususal way to implement an abstract method in ObjC is to declare it normally, and have it raise an exception when called (there is a particular kind of exception that's standardly used, but the exact name slips my mind... NoSuchMethodError maybe?).

Obviously, that's not really the same as Java or C++, where the compiler will force you to implement all the abstract methods, but this again comes back to ObjC's general unconcernedness with formal interfaces.
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #45
PowerMacX Wrote:Obj-C allows a lot of flexibility in comparison, but at the cost of hard to catch runtime errors, as early versions of both Project Builder and Xcode showed.
`hard to catch runtime errors' is a partly true. I say that because in the experience that I've had with Obj-C/Cocoa for the last few years, nine out of every ten (maybe even ten out of ten) of those errors were simple, silly mistakes on my part (calling an object that I released, etc.). Over time I have learned not to make those mistakes and now it is *very* rare to create a runtime problem that I can't track down in a few minutes.

Also, don't forget that with Obj-C you can query the actual names of the classes being called, pre-flight them to make sure they even have that method, and so on. Obj-C is not only flexible but informative when necessary.

Over-generalizing, but: With something like C/C++ there are mostly barriers to overcome. Something might not work in a large API and it could take a long time to figure it out. Whereas with Obj-C/Cocoa I might accidentally do something that actually works and I have to sometimes sit back and try to figure out how it figured out what I wasn't trying to do. Instead of breaking the flow of the program it might just skip past it and spam the log instead. Really cool stuff!
Quote this message in a reply
Post Reply