Accessing child protected members from parent - php

I've noticed that in PHP the following code works with no complaints:
class A {
public static function echoes($b) {
echo $b->protectedFunction();
}
}
class B extends A {
protected function protectedFunction() {
return "this is protected";
}
}
$b = new B();
A::echoes($b);
Example https://3v4l.org/JTpuQ
However I've tried this in C# and it does not work as the parent cannot access the child protected members.
My question is who's got the OOP principles right here? I've read through the LSP but it doesn't seem concerned with parent classes, so is it correct for a parent to access child protected members (like PHP assumes it is) or should it be restricted (like C# assumes it should be)?

The way that C# restricts access seems to be the most logical way to do it.
A parent should not be able to inherit anything from a child. And without inheriting anything from the child, the parent should not have access to the child's protected methods.

I think you might get problems letting the parent know something about the children. Because parents are used to extract and bundle behavior and attributes from multiple classes, so the way of information is just in one direction.
Maybe there are cases in which you need to access the protected attributes, but I guess wherever it is not needed avoid it.

PHP is a dynamically typed language. Function and method calls are not checked until that line of code is actually executed. In PHP you can have two objects instances from the same class with different methods. This works fine.
Statically typed languages like C# require to know the types of objects before execution. You can still use reflection to call children methods from the parent, but you can't add new methods dynamically.

Related

should my child classes inherit empty functions from parent class?

I'm trying to make a parent class and child classes, lets say the parent class is called functionality and has functions like add(), validate(), and delete(), and the child classes are driver and passenger , each of the child classes inherit the functions but needs extra parameters and different logic for each inherited function, should I define the function but leave it blank? how is this helpful apart from extendibility?, and should I define a different constructor for each child class because they have different extra variables?
class functionality
class functionality{
protected $from;
protected $to;
protected $date;
protected $name;
public function add(){
}
public function validate(){
}
public function delete(){
}
}
class driver
class driver extends functionality {
private $gasMoney
function add($from, $to, $date, $name, $gasMoney){
//some logic and adding to database
}
}
class passenger
class passenger extends functionality {
private $seatPrefrance
function add($from, $to, $date, $name, $seatPreferance){
//different logic than class driver and
}
}
is this an acceptable approach? and how would I define a constructer? should I define it in the parent class? does the child classes inherit it and can add more to it?
You shouldn't use inheritance for this, it doesn't make sense.
The main idea is that other parts of your application can receive an object, and they don't care if it's a passenger or driver, they just get some instance of functionality and call add on it.
Another reason to use inheritance if you want to take advantage of some shared behavior, so you don't have to reimplement a method.
If arguments are different based on the sub-class, there's no way anything can do something with the generic functionality class, so this is pointless.
You also can't re-use the method, because you are clearly overriding the method for each case.
Think about driver and passenger. Are there parts in your application that need to work with both? What is their actual common functionality? Anything that's not common does not go in the base class.
I know this is probably a contrived example, but it also doesn't make sense to 'add' a passenger name to an existing passenger.
If you call your class 'passenger', I would expect that to represent a single passenger, not multiple.
Learn OOP as a tool, not a religion.
If you meet an inspiring preacher, they might teach you a whole new way of thinking about the world, and suddenly you see everything in a new light. You change your diet, your daily routine, and which TV programs you watch.
If you are given a new drill as a present, you might get some scrape wood to test it out a few times, but after that you'll wait until you need to put some shelves up. You won't work out how you can pour milk through a newly drilled hole in your breakfast counter.
The example you have come up with is trying to do OOP for OOP's sake. It doesn't make any sense, because you haven't actually got a problem you're trying to solve.
In particular, don't pull out the inheritance drill until you need it. Start off by looking for ways to encapsulate state in private properties and define behaviour that is more than just accessing that state. As a silly example, $driver->canLegallyDrive() method might internally check the $insurance and $alcoholLevel properties.
Even when you find logic you want to share, composition (just storing one object in a private property of another one) is often better than inheritance. Inheritance really comes into its own when you need polymorphism - multiple objects which look the same on the outside but behave differently on the inside. And even then, learning to use interfaces rather than base classes will unlock more potential.

To store as a class parameter or normal php variable

I am new to OO concepts in PHP. I have a class called MY_ controller which is my base class. All classes extend this class. I am using MVC architecture. I am using caching in my system now. So i load the cache variable in the constructor of my base class. I use normal php variable like $cacheVariable in my function to store the value from cache. I was wondering if it would serve any help if i store it as a class parameter and use like $this->cacheVariable? In each function i get cache value like $this->cache->get('cacheVariable'); will it help if i get value from $this->cacheVariable
If you want to be able to use $cacheVariable anywhere else besides your constructor you'll want to use $this
public function __construct() {
//...
$this->cacheVariable = $this->cache->get('cacheVariable');
//...
}
Also remember, if you want your children classes to inherit this variable from your base class you will need to set it as either public or protected. If it's private children will not inherit it.
When you say "class variable" I assume you are referring to a property (property of an instance=. Note the difference:
if you have a class, say MyClassA, then in your scripts you will instantiate that class using the operator new (depending on your PHP version you can use a different constructor syntax it changed since PHP-5.3.0):
<?php
class MY_controller{
public $cacheVariable;
// constructor
function MY_controller($aValue){
// constructor code which loads cacheVariable, for example with parameter
$this->cacheVariable = $aValue;
}
public function someFunction(){
//... some code, then access the property
$cv = $this->cacheVariable;
}
}
$aController = new MY_controller(42);
?>
As you inherit from MY_controller, every instance of that class, will have access to cacheVariable through $this->cacheVariable.
The important thing I wanted to clarify is that it is an instance property, not a class one. For further reference on OOP in PHP, refer to the properties section in PHP's OOP manual and the inheritance section.
When you instantiate only one instances of your controller (derived from your main controller), its a conceivable solution.
In my opinion the better idea is getting variable directly from cache service everywhere you want in your class and don't keep it as a class property. The reason is simple: let's say value of some key from cache will be changed (or expires) in the other place than your class. If you have this value as class property you need to keeping eye on it every time you access this value but if you retrieving it from cache you just don't care (because the cache cares if value of some key doesn't changed or expired).

Can main classes access child class methods

If I have:
class main {
//hello
}
class child1 {
function love($v) {
}
}
class child1 {
function hate($v) {
}
}
function __autoload($file) {
include_once($file . '.php');
}
Is there a way I can set this up so that I can do
$main = new main();
$main->hate();
$main->love();
and still
keep them as seperate classes, and
use the autoloader for the child classes?
I think even if the child classes extend the main class, that I can't access the child methods from the parent class. Is that correct? If so, is there something like a reverse extends which injects the child class properties/methods into the main class?
Update 1
Okay, so it looks like there's nothing straight-up built in to php to acheive this (Thanks everyone for the answers). How about I write up my goal and maybe you or someone you know can suggest a way to acheive this?
I would like to have one main class. I then have a set of subclasses which operate like grouped function libraries. Each of these subclasses is __autoloaded when needed to acheive an end. So for example, I have a subclass of file upload & processing functions, a subclass of database interaction functions, a subclass of xml processing functions, and so on.
I want to use this like: call the main class at the top of every script $main = new main();. Then, later on, an image processing method from a child class (which has not been loaded) is needed, so I call
$main->methodFromChildClass(); which will cause that child class to be autoloaded and the method used.
I am hoping in this way to optimize which files are loaded, and keep things well organized. I'm fairly new to oop. Is there a way to achieve this type of organization now?
There is not such a language construct (not in PHP anyway - other languages offer mechanisms like mixins, which kind of work like that), but there is a technique to do something like that called inversion of control.
class Main {
public $child;
public function __construct($child) {
$this->child = $child;
}
}
$main = new Main(
new Child1()
);
$main->child->love();
This is very simplified example, that does not show full potential of this technique. For more information search for 'inversion of control' and 'design patterns'
I think you're interested in is called traits, which are not available in the current release of PHP, but will be in the next version, and is available in trunk if you check out the source from SVN and compile yourself.
For more information, see http://wiki.php.net/rfc/traits
Not to my knowledge, kinda violates the whole concept of OO programming. The main class should have the methods and properties which need to be used by all child classes of the main class, and then the child classes have methods and properties that only they will need to use.
I suppose if you really wanted to, you could store a child class object inside a main class object and do something like $main->child->hate(); but that would be sort of recursive, because if the child extends the parent class, and if the child was created and stored on the parent's construct, then you would wind up with an infinite loop of the parent creating the child which creates a new parent inside it which creates a new child which creates a new parent ad infinitum. Though you could get around that by simply having a method that would have to be manually called in order to create and store the child.
With the code you gave, it's not going to work.
If child1 extends main, you can call hate() method only by creating instance from the child1 class or by introducing the hate() method in the main() class.
Child classes inherit methods from Mother classes but the reverse is not true.
What exactly are you trying to do ?
You can use magic to simulate that behaviour, but "clean" is something different
class main {
public function __call ($name, $args) {
switch ($name) {
case 'hate':
$x = new child1;
return $x->hate();
break;
case 'love':
$x = new child2;
return $x->hate();
break;
}
}
}

Is there any way to achieve multiple inheritance in php?

Lets say I have a parent class
class parent { }
.....
This parent has three sub class
class child1 { }
class child2 { }
class child3 { }
and these child classes have further smaller parts like
class child1subpar1 { }
class child1subpar2 {
public function foo() {
echo "hi";
}
}
class child2subpar1 { }
class child2subpar2 { }
Now, how to sum this whole up like
class child1 extends child1subpar1, child1subpar2 { }
class child2 extends child2subpar1, childsubpar1 { }
class parent extends child1,child2,child3 { }
I need to execute the methods in its inherited classes and do something like this
$objparent = new parent;
$objparent -> foo();
No, but multiple inheritance is generally considered a bad practice. You should favor composition instead, so you just use instances of classes you wanted to inherit inside your class.
And now when I look into your question again, it's not even an inheritance issue, you should use composition. Maybe if you provided more detail what you expect that class to do, we should answer more accurately.
UPDATE:
You will need to create one method for each of these classes' method which you would want to use - it's called Facade design pattern. Or maybe you are not aware that you can call methods of inner objects like this:
$parent->subObject->subSubObject->wantedMethod();
Facade pattern:
http://en.wikipedia.org/wiki/Facade_pattern
in your case facade wouldn't be anything else than creating one class and define every single method you want to use, and inside that method calling any method of any of your inner instances. But i really don't see any benefit coming from this instead of calling
instances and methods hierarchically
Seems like you're really confused about OOP.
Parent class has no awareness of its children. If you want to execute a child class, you need to create its instance.
Multiple inheritance is also not allowed in PHP (as well as many other popular languages like Java).
It might be worth looking at aggregation - passing smaller sub classes into child or event parent class. also, you can use implement multiple interfaces to force subclasses to have a set of required methods.
What you're doing is really backwards. Inheritance is used to bestow common, shared functionality upon objects without code duplication. The inheritance goes from Parent to Child, everything the Parent can do, the Child can do as well, but it may do more (it extends the functionality of the parent).
class Parent {
function everyoneCanDoThis() { }
}
class Child extends Parent {
// I can implicitly use the everyoneCanDoThis() function
function onlyChildrenCanDoThis() { }
}
Since this is a top-down structure, the Parent should not rely on any specific Child. The Parent does not execute or call functions of a Child. Only you call functions of a Child, but these functions may be inherited from a Parent class.
You should put everything you want every object to be able to do in a Parent class. Specific functionality that's only relevant to a specific object goes into a Child.
Multiple inheritance is a different can of worms that's not possible in PHP, for good reasons. Come back to composition, as suggested elsewhere here, when you get the basics of inheritance. :)
Composition just means that you take several objects and hold references to them in another object. It has nothing to do with inheritance, as each of these objects may or may not inherit from a Parent class and they're still individual objects.
class ComposedObject {
private $part1 = null;
private $part2 = null;
public function __constructor() {
$this->part1 = new Part1();
$this->part2 = new Part2();
}
public function doTask() {
return $this->part1->doSomeTask();
}
public function doOtherTask() {
return $this->part2->doSomeOtherTask();
}
}
The ComposedObject does not have any functionality itself, inherited or otherwise. But it holds two other objects that each carry some functionality. The functionality in the "parts" may be exposed directly, so they're called like $composedObject->part1->doSomeTask(), they may be encapsulated as in the example, so they're called like $composedObject->doTask() and are internally delegated, or you may use some __call() trickery to automatically delegate functions called on the composed object to one of its "parts". This has the same problem as multiple inheritance though; if two "parts" both contain a method of the same name, which one do you call?
+1 to the others. You really have it backwards. Children ALWAYS extends their parents.
But there is even something that can act kind of like multiple inheritance in PHP: The Decorator Pattern.
I wrote an article about it on my blog here.
A class can implement more than one interface, which is a slightly different thing.
When you inherit from a parent, you get everything it has unless you choose to override something, plus you can extend it by adding additional more specific stuff, but the parent should not know anything about the child.
When you implement an interface, the interface defines methods but it doesn't implement them. It is up to you to implement it. Different classes can implement the interface methods however they want as long as they follow what the interface says.
Inheritance tends to be overused and leads to bad programs. Perhaps if you told us what problem you're trying to solve, one of us could suggest how you can structure your classes.
Using Interface in Php maybe solve the question.

How to design an inheritance with changing parameter types in php?

The idea is to create a DOM-like tree. But there are some restrictions, that only certain types can actually contain the other.
I want to use an interface|abstract class|superclass to implement some well known js-functions as appendChild, replaceChild etc.
I'm using the classes page, block and item, where pages can contain blocks and blocks can contain either blocks or items.
Example: Page is a web page, block could be an list element and item could be an list item element.
But these objects contain more than just html-data and the concepts goes beyond just plain HTML representation. It's an overall idea of managing items, wether they have an actual representation or are just abstract objects. The concept itself works for many different hierarchies.
What I want to achieve is to reuse as much code of the parent class as possible (adding a child is basically the same for all classes) but to differ the type hints to match the allowed types to add as a child.
There are basically four ways I found out myself:
I use an interface, which allows me to type hint to the superclass but not to change these.
I use a superclass with public methods, so i can redefine the type hints (which is totally against usual practices when heriting preconditions).
I use a superclass with protected methods, which seems still being quite quirky.
I get rid of any superclass and just define almost the same class several times.
I use a method to check for the type, despite the feature of type hints.
So, if anyone is still willing to answer I'm happy for any proposition, idea or hint, which option to choose. I hope I could describe the issue well enough.
And if there is something i missed I'm thankful to hear it ;)
Code
Superclass way (works, but breaks precondition inheriting practice)
class Base {
public|protected function appendChild(Base $child) {
// do stuff
}
}
class Block extends Base {
public function appendChild(Block $child) {
parent::appendChild($child);
}
}
Interface way (Does not work. It must not)
interface Interface1 {
public function appendChild(Base $child);
}
class Base implements Interface1 {
public|protected function appendChild(Base $child) {
// do stuff
}
}
class Block extends Base{
public function appendChild(Block $child) {
parent::appendChild($child);
}
}
Edited parts are bold
Interface makes most sense to me. You can have one class that plays multiple roles, as it can implement multiple interfaces.
// you don't need any methods in the interfaces
class Foo implements Inline, Block {}
will work with both:
appendChild(Inline $foo); and appendChild(Block $foo);
and interfaces can extend each other, so there can be common interface for all your objects.
You can still use inheritance to reuse implementation, and you'll have flexibility to use inhertiance tree strictly for reuse of implementation, not limited by your page logic (you'll never be forced to make StaticSimpleton extend HeavyDatabaseyWidget).
If not interfaces, I'd go for option 5: just make appendChild call $child->canBeChildOf($this) and/or $this->accepts($child). Again, logic and implementation will be independent, and you'll have a lot of freedom with your logic.
PHP does type checks at run tmie, so use of type system doesn't buy you much anyway.

Categories