With instance members (non-static) I know we can, but with static members I DON'T KNOW IF WE CAN, if we can, is it good practice?
Related
Just startet to feel the real usefulness for classes and methods (Object Oriented Programming) in PHP. However I still lack the understanding and experience declaring methods and variables the proper way.
I what cases should I declare a method/variable static VS declaring it non-static? What questions do I ask myself to answer this question?
Static means that you can access the functions without first creating an instance of the class. This makes it a lot like a normal function. You tend to make functions static if you want to group functions together that are related, but do not need a specific instance of the class to run.
Non-static members require an instance of the class. Typically you will use this.
If we have a class Circle and it has function area(), then it would be non-static as it needs a specific circle to find the area of. Now imagine we have a PrintText class with a printBold() function. We don't need an instance since it only depends on the inputs. However it is convenient to have the PrintText class because we could have printBold(), printItalics(), etc.
The basic rules of inheritance and visibility go as follows:
Accessing private members from within a class is OK.
Accessing private members from a subclass is not OK.
Accessing private members from a superclass is not OK.
Accessing protected members from instances of a class is OK.
Accessing protected members from instances of a subclass is OK.
Accessing protected members from a superclass is not OK.
Somewhat less obvious are the rules for accessing these properties from another instance of the same class, though it is spelled out clearly in the documentation:
Accessing private members from another instance of the same class is OK.
Accessing protected members from another instance of the same class is OK.
This happens because the object has access to the class spec. It seems to be due to a quirk of implementation in the language, albeit one that we can rely on. What I'm curious about is the rules of visibility from other object instances both up and down the inheritance chain. What I expect is:
Accessing private members from another instance of a class is OK.
Accessing private members from another instance of a subclass is not OK.
Accessing private members from another instance of a superclass is not OK.
Accessing protected members from another instance of a class is OK.
Accessing protected members from another instance of a subclass is OK.
Accessing protected members from another instance of a superclass is not OK.
Is this right?
Yes, it's right.
The visibility rules are based only on classes, instances have no impact. So if a class has access to a particular member in the same instance, it also has access to that member in other instances of that class.
It's not a quirk, it's a deliberate design choice, similar to many other OO languages (I think the rules are essentially the same in C++, for instance). Once you grant that a class method is allowed to know about the implementation details of that class or some related class, it doesn't matter whether the instance it's dealing with is the one it was called on or some other instance of the class.
Not entirely. It's right that the rules are only based on classes, and it does not matter if it is the same instance or another instance and that was basically your question.
However, you made a mistake about protected in general. From the documentation:
Members declared protected can be accessed only within the class itself and by inherited and parent classes
(highlight added)
So, the following statements are wrong:
Accessing protected members from a superclass is not OK.
Accessing protected members from another instance of a superclass is not OK.
This is less of an issue, and more of a best practice question - I know these are subject to opinion, but I'm sure there must be a standard convention for this particular problem.
Let's say I've got two classes, Account and Associate.
Account contains several methods which are useful to Associate, and so naturally I'd extend the Account class to Associate.
However, an issue of course arises when I have two methods with the same name e.g. create().
So far to counteract this instead of extending the parent class, I've been instantiating it as a variable in the child classes __construct() method, and then calling methods through that, e.g. $this->Account->create();.
Is there another way, e.g. a norm for using an extended classes methods while still having a method of the same name in the child class?
Any answers would be greatly appreciated!
Account contains several methods which are useful to Associate, and so naturally I'd extend the Account class to Associate.
No, this is not naturally, you are misusing inheritance. Or would you say that an associate is an account? If it has an account, use composition. If not, but the account class has methods that are useful for the associate class, they probably shouldn't be in the account class at all. Extract them to one or more other classes which can be used by both, Account and Associate.
The child class method will be called using $this if you are within the child class methods. If you want the parent method though, you'd call parent::create(); from within the child method.
But that is if you absolutely need to extend the Account class, which sounds unnecessary. If the "Account" class has public methods then you don't need to extend it, you can just call them after instantiating the class:
$account = new Account();
$account->create();
Or, if it is a public static method:
$creation = Account::create();
From some brief fiddling about, I find I get an error when overriding superclass methods in a subclass when I do the following:
Override a protected superclass method with a private subclass method
Override a public superclass method with a protected or private subclass method
However, If I do it in the other direction, no error is thrown:
Overriding a private superclass method with a protected or public subclass method
Overriding a protected superclass method with a public subclass method
This seems counter intuitive to me - I was expecting it to work the other way around in order to enforce information hiding and encapsulation. This appears to allow poor design by allowing internals to be exposed in a way that may break other methods and I can't see a case when this would be a good idea. Why has it been implemented this way and what have I missed?
Also, is this standard practice in other programming languages?
What you call "enforce information hiding" is something, that may break subclasses, because suddenly properties and methods may disappear. You cannot break things by loosing restrictions this way.
With private is a bit different: In this case the property/method does not exists from the child class' point of view. Thus there is no reason, why a subclass may not introduce a property with that name, because it will be a different property.
You are right, that this may lead to poor design, but you can always build an application with poor design.
You can't decrease the visibility of class members, only increase them.
Imagine a class A which has a public method, and a subclass B would make it private. B could be treated as a type A, for which it is assumed that it has that public method.
If a superclass exposes a method publicly, then all its subclasses must also expose the same method (or an overridden version), therefore reducing the accessibility of a method is a subclass is illegal in PHP (and pretty much every class-based OO language).
The opposite is not true, so increasing the accessibility of methods in subclasses is perfectly fine.
If you think expossing a private/protected method in a subclass represents a problem, just make the method final.
See it this way: by NOT making a method final, you are allowing any subclass to overriding it at will; this obviously includes increasing its visibility.
i'm trying to follow DRY and i've got some functions i have to reuse.
i put them all as static functions in a class and want to use them in another class.
what is the best way to make them available to a class.
cause i can't extend the class, its already extended.
should/could i use composition?
what is best practice?
thanks!
If they are static then just call them from your second class.
First_Class::method();
Public class methods (vs instance methods, e.g. non-static) are always available from the global scope, so you could just call them statically where needed. But keep in mind that static methods are death to testability and hard couple using classes to the global scope and the used class. You want to avoid that, so it's better practise to get rid of the static methods in favor of instance methods and passing in the dependency/object instance through the constructor or a setter. Add an interface Type Hint if you want to make sure the passed instance has a certain set of methods.