Note: It's been years since I did PHP, please forgive minor syntax mistakes.
It seems you're misunderstand what
final does and why it should be used.
final public function getName()
final keyword doesn't prevent
this->name from being changed. As evidence by the following example:
public function __constructor($name)
this->name = $name;
final public function getName()
public function setName($newName)
this->name = $newName;
final does is prevent inheritance overriding. Normally, derived classes can override the implementation of a base class' method, e.g.:
class NobleDog extends Dog
public function getName()
return "Sir " . $this->name;
If you assume my implementation of
NobleDog, you can see that you can always change a dog's name, but even when you change their name to e.g. "NEWNAME", a noble dog will still be called "Sir NEWNAME", whereas a normal dog will just be called "NEWNAME".
getName() final in the base class, the
NobleDog derived class cannot override this anymore, and it therefore cannot e.g. prepend "Sir" to a dog's
final public function registerDog(Dog $dog)
this->registredDogs[$dog->getName()] = $dog;
The problem here is that you register the dog with a specific name, and if that dog's name changes afterwards (for whatever reason), the registration in
registredDogs itself is not updated and still uses the old name.
this->name is made reasonably immutable in your
Dog class, that is currently not an issue. However, it's always possible that someone later decides to add a method to
Dog that does change its
Whether you consider that a real issue you need to actively protect against is up to you. I tend to expect developers to understand that this name shouldn't be changed since there's no setter in the class and it's made
private, but your mileage (and developer team) may vary.
Sadly, there is no real "readonly" property in PHP, which would prevent any issues with this name unexpectedly changing.
If your main concern is being able to query
registredDogs with the current name of the dog, regardless of whether it has been changed or not, then you shouldn't set its key based on the dog's name, but instead you have to dynamically query your collection and find the matching name. This ensure that the current name is the one you're matching against.
public function getDog($name)
foreach($registredDogs as $dog)
if ($name == $dog->getName())
$found = $dog;
This is of course less performant than an index-based lookup, but it does allow for changed values to be accounted for.
Please excuse any syntax errors I may have made, it's been a while since I did PHP.
Overwriting the selectManyAndReturn method can change the behavior of the class, people can overwrite it and run selectOne for example instead of selectMany, OK, I can make this method final also to prevent this, but by this way I am also preventing people form adding new features to the method
Just because someone can override a method doesn't mean that literally any valid code they write is therefore a correct implementation.
Selecting one element instead of many feels like an incorrect implementation, but e.g. selecting many elements and then doing some additional filtering on that array sounds perfectly fine.
Developers writing incorrect (but syntactically valid) code is not something you can prevent. If it were, then we would've either solved P=NP or we wouldn't never need to test/debug ever again.
What should I do? Is forgetting final and private methods completely good idea? like many applications and many programming languages? or Can you tell me when exactly we should make a method final?
First of all, for this specific issue, assume that developers will write a correct implementation when overriding your method. The correctness of what they do isn't relevant here.
What is relevant, is whether you want developers to be able to change your method implementation in a derived class. Sometimes you want that, sometimes you don't. That's very contextual.
If you're making a base class which is intended to have some reusable component that is forced to be consistent between derivations of this base class, then you're likely going to want to be using
This is slightly language specific. PHP makes everything overridable by default and requires you to explicitly prevent overriding. C#, by comparison, makes everything "final" by default and requires you to explicitly make a method
virtual to enable overriding.
I'm a C# dev, so I'm naturally a fan of opt-in overriding, i.e. nothing can be overridden except when explicitly made to be. But PHP devs are liable to think the other way, because that's what they're used to.
I'd suggest sticking with whatever your language chose as the default behavior, simply because it means that you don't have to pepper your
virtual keywords all across your codebase.
Edit: Robert Harvey makes a reasonable point that you might want to be more liberal with
final when dealing with third parties using your code. It all depends on whether abusing it is actually harmful to you, or simply renders the third party's product defective. In the latter case, there's less reason for you to actively defend against this.