Hi I’m newly registered to sitepoint and this is my first post (excluding my intro topic).
I’m not looking for an answer to a specific problem, rather I’m trying to further my education. I’m happy to be linked to tutorials or books, but I’m hoping this question is simple to answer.
What I already (think I) know (feel free to correct errors):
A class is a collection of functions (and other stuff like methods, templates etc?)
Functions such as
cat_walk
cat_hiss
cat_claw
And I can create a new object from this class. So I could either make 1 cat or an army of cats each with their own actions all separate from one another.
This is where my knowledge stops.
I’m trying to understand things like:
What if I wanted an army of cats? Would I create another class to store all the cats in, with functions for their actions such as cat1_army1 attack cat1_army2?
Would these be stored as array variables with each army of cats in separate arrays, or would I have object_army1 containing all the cats from army 1 and a second object object_army2 with the other army?
My first thoughts would be to have a hierarchy of objects such as
Battle
-army
–cat
But is this the correct thinking?
I once read an awesome tutorial that really helped - but I lost the link
Many thanks in and advanced, and a big hello to potential new friends.
I don’t really understand how object data flows between objects
Let’s start by taking a look at those cat armies of yours
How you wish to store these really depends on what you want to do with those armies. You could simply store them in an array, so you can iterate over them and tell each cat what to do. You could also store them in an object and add methods to that object that will manage the behavior of all cats in that army. Imagine methods like “attack”, “defensiveStance”, “offensiveStance”, etc. With that you can tell the Army class to do something, and it will in turn tell each cat what to do, according to the command you gave the entire army. That you way you don’t have tell each cat separately what to do; this is known as delegation.
As for the hierarchy, your idea is not quite right. You could indeed use those classes, but they don’t make much sense in an hierarchy, since Battle is not an abstraction of an Army (but rather multiple armies) and Army is not an abstraction of a Cat (but rather multiple cats).
As an example of an hierarchy, you could have something like this
Animal
FourLeggedAnimal
– Cat
i.e., Cat extends FourLeggedAnimal, FourLeggedAnimal extends Animal. So Animal contains methods all Animals should have (like “sleep”), FourLeggedAnimals contain methods that only pertain to animals with four legs (like “sit”), and Cat contains methods that only pertain to cats (like “purr”).
Using this hierarchy you can call all these methods (“sleep”, “sit”, “purr”) on a cat object, even though only one of them is defined in the Cat class itself; all the other functions are inherited. Another thing to note here is that you can* override methods from higher classes, so if the “sleep” method of a cat should be different than the default animal sleep (because you also want it to purr every now and then) you can put a method “sleep” in the cat object, and when you call $cat->sleep() it will execute that method, and not the one in the Animal object.
Hope that makes things a bit more clear, and if not feel free to ask away
depending of the access modifier of the methods, but let’s not get in to that quite yet
Some of the things you said sound familiar and are starting to make a little sense.
Could you go into methods & delegation a little more? You state that a method will manage the behaviour of all cats - would you elaborate?
I’m really trying to get my head around data flow around my code, and make sure the things I do are best practice
The reason I picked combat was because of multiple elements FYI (no idea why they were cats).
Do I understand this right:
I have a class cat with “attack” method (amongst the other actions such as purr and beCute), with abstract “bigCat->attack” and “smallCat->attack”?
class CatArmy {
private $cats;
public function attack($target) {
foreach($this->cats as $cat) {
$cat->attack($target);
}
}
}
then you can just do $army->attack($someOtherCat); and that will tell all cats to attack the other cat (poor thing :()
You could have of course put the foreach loop in your main code, but this has the advantage that
it’s short and sweet
suppose you have this attack multiple times through the code, and at one point you decide you don’t want all cats to attack, but just half the army (leaving the other half to do something else). In that case you need to modify code all over the place. With this class you just change this one method and you’re done.
I’d put it the other way around: Cat is an abstract of BigCat and SmallCat
then you can indeed put an attack() method in Cat, and override them in BigCat of SmallCat, so you have Cat with a normal attack, SmallCat with a small attack and BigCat with a big attack
I should have said that. Yes, cats is an array. Something like
class Army {
private $cats=array();
// add a cat to the army
public function add($cat) {
$this->cats[] = $cat;
}
// a cat left the army
public function remove($cat) {
$pos=array_find($cat, $this->cats);
unset($this->cats[$pos];
}
}
very crude and probably doesn’t run, but you get the idea
sorry for all the questions - i’m just trying to figure out how data should flow around classes.
does this look right to you so far - this is how im understanding things right now:
<?
class army {
private $cats = array();
public function attack(){
foreach($this->cats as $cat){
$cat->attack();
}
}
public function addCat($cat){
$this->cats[] = $cat;
}
}
abstract class cat {
abstract function attack(); //I've done this like this because php.net do it, and I can only assume this is to dictate that all cats are required to have the function "attack()"??
public function combat(){
$this->attack;
}
}
class bigCat extends cat {
function attack(){
print("super mew power pew pew pew\
");
}
}
class smallCat extends cat {
function attack(){
print("nyan nyan attax mode!\
");
}
}
$army1 = new army;
$army1->addCat(new bigCat);
$army1->addCat(new smallCat);
$army1->attack();
?>
$class->method() is a dynamic call you can make when you’ve made an instance of a class. $class::method() is what you can call on a static function of a class; in that case you don’t have to create an instance, but can create the class immediately
class Cat {
function purr() {
echo 'I\\'m purring!';
}
}
class Logger {
static function log($message) {
echo 'Log: ', $message;
}
}
Cat::purr(); // can't do that
$cat=new Cat();
$cat->purr(); // okay
Logger::log('Hello world!'); // okay
you normally use static function for classes you don’t need multiple of (like a Logger, just having one is enough)
Yes, databases are also an example of where you usually want to do this (unless you need to connect to multiple databases, in that case you’d probably want multiple instances, or a Registery pattern, or something like that )
Anyway, I just saw your code and that looks fine. Indeed, the abstract function attack() is to force all children of the class to implement that function; if they don’t PHP will throw an error
That you can implement other functions, so all child classes use the functions of the abstract that are already implemented. Of course they are free to override them if they wish.
Other than there aren’t any more benefits I think; it’s just to give you a mock class to base other classes on which you can be sure have certain methods.
I think I’m with you now - so I don’t have to manually set 100 attack functions on all 100 types of cat warrior unless I need the attack to do something diferent - I can just use the abstract attack. That makes sense.