TheIdeasMan wrote: |
---|
I was thinking they have different numbers of properties and different properties depending on what sort of weapon it is. A dagger would have less properties than a sword, and a Bow would have different properties than other types of weapons. |
This is another reason why it's a misuse of inheritance.
Inherited classes ideally should have the same interface as their parent class. Only the implementation should differ.
For example, you say that Bow has an additional property that Dagger does not have. How can you use that property if only given a CWeapon* pointer? You'd either have to downcast, defeating the entire point of having a shared parent.... or you'd have to give a dummy property to the Dagger so it can be accessed via the CWeapon interface.
Since the weapons themselves have no implementation, there's nothing to really distinguish them other than number of properties. Therefore a class hierarchy seems inappropriate to me.
Does this mean that you would have different structs to accomadate this? |
No. Just have one. The struct will have entries to accommodate all weapons. For some weapons with fewer properties, those values will simply go unused.
With the classes, I only need 2 Attack functions to cover player vs Enemy and Enemy vs Player: |
I'd think you'd only need one:
virtual void Attack(CActor*, const Weapon *);
Or do CPlayer and CEnemy not have a common base class?
Looking back at the thread you linked... I noticed that CActor doesn't exist. I could've swore I saw it there.
Anyway that would be a better example of inheritance. Players and Enemies do the same things (move, attack, get hurt, etc), but in slightly different ways. That is... the interface (what they do) is the same... but the implementation (how they do it) is different. That's what inheritance is for... and is where it truly shines.
But then again... I'm not sure why the object being attacked would need to know who attacked it. Ah well.... I guess that could be useful...
I am guessing there will be different behaviour for different weapons. |
Then that's another matter entirely. If there's differing behavior then it would make sense to keep that behavior in the CWeapon class and provide a common interface by which that behavior can be triggered.
Though it's hard for me to explain that further without knowing details. I kind of wish SGM3 was involved in this thread so he could contribute and clarify the behavior he's looking for.
I had the distance classes CSlopeDist, CVertDist, CHorizDist; the Angle classes CBearing, CZenithAng. All of these classes have only one member variable - either a Distance or Angle respectively. So now I could have function calls: |
That's a strong typing technique and can be very useful.
The question I have for you is did you inherit those all from a common base class? If so, did it provide any real benefit for you? If you're passing derived types around to different functions... what good does having a common parent do you?
After all, the purpose of having a common parent is to treat different types similarly... but you are intentionally doing the opposite there.
Going back to the original question - how to communcate between objects without getters & setters? |
Establish an interface with which they can communicate. Getters and setters sort of work for that... but expose implementation details.
In the case where you want Weapons to have different behavior (ie: inheritance is justified) and want to use that behavior to impact another object (deal damage to an Actor)... then I'd approach that situation like this:
Determine the fundamental purpose of a weapon.
What does a weapon do:
- It inflicts damage by attacking.
- It might also offer some defense (ie: using a sword to block another sword)
- It might have some kind of stat-boosting enhancement
- It might have some magical ability (ie: holding a staff up to spit flames or something)
There are all areas that need an interface. Now... to my eye... the first 3 of these 4 points are simply statistics tracking and therefore do not warrant the use of a class hierarchy. But assuming that is not the case....
Design an interface that allows those purposes to be communicated to other objects. In the case of dealing damage... maybe that is just having a function return an int indicating how much damage is being dealt (it might look like a getter, but since it's implementation dependent, it might not always be one).
Or... if that's too simplistic for your needs you can wrap it up into a Damage struct. This would allow you do give elemental properties to an attack... or other status effects (ie, swords might induce bleeding, blowdarts might poison, etc).
That struct becomes the common interface. You can then pass that to the Actor and have it respond appropriately.
In the end you end up with something that seems similar to a getter (very much like mik2718's "damageCaused" function)... but for the purposes of this example we're assuming it's not a getter because you said weapons have unique behavior. (which kind of makes this a difficult example because how unique can the behavior of producing damage really be?)
I hope I am not coming across as being stubborn clown !! |
You're not. Don't worry so much about offending people by asking questions ;)
This is a very complex topic and you'll hear tons of different opinions from different people. All I can do is offer my own.