On my side i would instead use these classes:
Interface iWeapon {}
Interface iAttacker {}
Interface iAttackable {}
Class Human Implements iAttacker, iAttackable {}
Class RangedWeapon Implements iWeapon {}
Class Colt extends RangedWeapon {}
Class M4AA extends RangedWeapon {}
Class Sniper extends RangedWeapon {}
Class Shotgun extends RangedWeapon {}
Let me explain them now:
iWeapon
Describes a weapon, the different getters, setters and a few actions such as DoDamage() or GetRandomAttackDamage(). Its as you wish. This interface allows you to define a weapon'S basics. You could apply this to the Weapon class or any other class that derives it, but i'd keep it to at least one basic class. The goal of the interface is to force all weapons to addopt the same behavior, it has attack damage, range, maybe charges? (Ammo)
iAttacker / iAttackable
Describes something that can attack or be attacked. These interfaces will usually provide functions that determine the ability to attack (is it stunned, immobilized, disabled?) or be attacked (invisible, invincible?) and provide functions to attack the other implementation. Humans or any other creature will implement these to say, HEY, i CAN attack AND be attacked. This interface would also provide getters and setters to control the weapons these creatures carry, maybe armors to prevent damage to them?
About interfaces
Remember always that classes represent something RELATIVELY concrete. If you are naming your class "Attacker" or "Target" you might be missing the point of a class. A class and object representing something tangible. In the other way around Interfaces represent actions or roles that classes may take. They only specify what one can do, they don't provide the implementation per se, they tell what that object will implement and thus DECLARE what they can do.
Hope this helps :)
Regarding the correct implementation of properties here is what i suggest:
class Player implements iAttacker, iAttackable {
protected $playerClass;
protected $race;
protected $weapon;
protected $armor;
public function setClass(playerClass $class){
$this->playerClass = $class;
}
public function getClass(){
return $this->playerClass;
}
public function setRace(race $race){
$this->race = $race;
}
public function getRace(){
return $this->race;
}
public function setWeapon(damagingGear $weapon){
$this->weapon = $weapon;
}
public function getWeapon(){
return $this->weapon;
}
public function setArmor(protectiveGear $armor){
$this->armor = $armor;
}
public function getArmor(){
return $this->armor;
}
public function attack(iAttackable $target){
//Check we can attack
if(!$this->canAttack()){ //Check we are not immobilized or disabled
throw new CannotAttackException($this->getNonAttackingReason());
}elseif(!$this->weapon->canFire()){
throw new CannotAttackException($this->weapon->getNonFireableReason());
}
//We can attack, roll the damage
if($target->isAttackable()){
$target->sufferDamage($this->weapon->rollDamage()+$this->race->getRangedDamageBonus());
}else{
thrown new CannotBeAttackedException($target->getNonAttackableReason());
}
}
}