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;
}
}
}
Related
I'm working on a WordPress project. There is a child theme implemented, and the parent one has a class to show authors' links. We have implemented a feature to support multiple authors per post, then we have our own methods for showing the proper links (not a single-author link, but many links joined depending on the authors count).
The complete scenario:
Theme: Newspaper
File: td_module.php (includes/wp_booster/td_module.php)
Class: td_module (abstract, many other classes in the parent theme inherit this one)
Method: get_author()
There are many other classes inheriting td_module in the parent theme, hence I cannot just extend td_module in my child theme since every change to the parent theme would be lost when the theme gets updated
Somehow I need to expand this method to show something different, but I don't want to change the method in the td_module class: even when it would be the fastest / most secure solution, this code would be overwritten on every theme upgrade.
This method is widely used in the Theme, that's why is that important to add some code here.
Why I still have some hope: There is a WP filter td_wp_booster_module_constructor, being called on the constructor of td_module class. The problem is that this class doesn't have any other filter on the method for showing the authors, but just the td_wp_booster_module_constructor filter call on the constructor.
The base PHP (and OOP) question: is it possible to expand / replace a method by using this filter in the constructor somehow?
Some code to clarify:
abstract class td_module {
...
function __construct($post, $module_atts = array()) {
...
// Can I change the get_author behavior by using this filter?
apply_filters("td_wp_booster_module_constructor", $this, $post);
// This is the only filter available in the entire class!
...
}
...
function get_author() {
$buffy = '';
// Code for generating author link ($buffy .= ...)
...
// This function doesn't have any apply_filter, there are no filters available
return $buffy;
}
}
Basically, you can't modify a class definition at runtime. The fact that you have a filter available on the constructor is a red herring and really not relevant.
Either the get_author() has some facility to change it's behaviour from outside class definition (in Wordpress parlance, filter and action hooks), or you simply cannot do it.
Outside of Wordpress, in an application with a proper dependency inversion container, you should probably do this by decorating the class and having all class consumer use the decorated class.
But since you have no way of telling class consumers to use one or the other, and a lot of code out of your control is presumably instantiating the class directly, something like this simply won't fly.
There is one extension, Runkit, that allows for changes of behaviour and definitions at runtime. there is even a method to modify a method definition. although I have not tried the extension, and do not know if it runs in an updated PHP runtime.
Note it is almost certainly a very bad idea to do this on production code, and that since you are dealing with code out of your control anyway you can't even be sure you would be changing the definition before it's used for the first time.
I've also found a repo for Runkit that says that it almost works on PHP 7, if you are absolutely convinced on going that way.
Your issue is that the base class is vendor code which you did not write.
So create a class in between your classes extending it!
Job done!
<?php
class SomeWordpressCrap
{
public function doSomething()
{
return 'something';
}
}
class YourAwesomeNewClass extends SomeWordpressCrap
{
public function doSomething()
{
return 'something better!';
}
}
class OneOfYourExistingClasses extends YourAwesomeNewClass
{
}
UPDATE So it turns out the OneOfYourExistingClasses is also vendor code, so the above solution will not work.
However! You could use Roave's "Better Reflection" lib, which you can find here https://github.com/Roave/BetterReflection
This will allow you to "Change the body of a function or method to do something different", which I believe is exactly what you need. Good luck!
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.
I have started writing a library of e-commerce classes in PHP as abstract classes with the intention of forcing the implementation of concrete classes to use a load() method which loads data into the objects:
abstract Cart {
abstract function load();
// other stuff ...
}
class MyCart extends Cart {
public function load()
{
// pull in data from anywhere ...
}
}
I was wondering if this is the right way to go about doing this...
I want to:
Keep the core library un-touched.
Keep it very simple, we intend to re-use this code and other people will be implementing it.
I've heard about adapters and things, although I haven't looked into these (yet).. can anyone point me in the right direction?
Cheers,
John.
Instead of using an abstract class, I would recommend using interfaces for this purpose:
interface Cart {
public function load();
// other stuff ...
}
class MyCart implements Cart {
public function load()
{
// pull in data from anywhere ...
}
}
Interfaces are used to describe the structure of a deriving class, it's the best way if you want to add different classes all offering the same methods. Another advantage would be that a class can only extend one parent class (i.e. your Cart class) but can implement several interfaces.
Read more about interfaces on PHP.net, here's one excerpt underlining why I think this pattern would fit your requirement:
Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.
I have an application in which a number of objects are all extending an abstract class which defines methods like create() edit() retrieve() and delete(). Since each of the child classes use the same logic for these functions, the abstract class defines that default behaviour, and in the few cases where it needs to be augmented, the child classes can override or use the hooks I've built in.
Now I'm having the situation where some of the child classes need to be made immutable, meaning that they shouldn't have edit() or delete() methods. This need sounds to me like a job for an interface named something like immutable which the immutable classes could implement. Problem is that interfaces don't stop methods from being called, they just enforce a method's existence. So this is obviously not going to work.
Making two parent classes, one for mutable objects and one for immutable ones is ugly and is probably asking for problems down the line which maintenance. I could have the immutable objects override the offending methods with an empty method that did nothing, but that also seems messy and like I'm not doing proper OOP at that point.
So what would you suggest as the best way to allow a large set of classes to all inherit a set of methods, but for some of them to not inherit all of the methods? (The application in question is written php, but general OOP techniques from any language can still be helpful).
create an immutable-base class as a child of the base class.
the immutable-base should implement final overrides of edit() and delete() which do nothing or throw an error.
Final, so that all immutable children are guaranteed not to be able to edit or delete
bonuses of this strategy
easily check if an object is immutable by testing for instanceof immutable-base
easily change objects from immutable and back again by modifing what it extends
Actually creating classes that have empty methods or throw errors is bad - such methods are confusing, they take up space and do nothing.
A better approach would be to make the immutable class the base class and make the mutable class extend it with adding methods for modification. This way each class has only those methods, that really belong there.
I like Java's approach to this. Throw an exception. Create an UnsupportedOperationException and for those implementations that shouldn't use a specific method throw one to let the user know they can't use this functionality for this implementation.
Another thought I wanted to throw out as a possible solution. Classes could implement an interface that looks like the following:
Interface Immutable {
const immutable = true;
}
and then the Base abstract class can write the delete() and edit() methods with
if (!$this->immutable) {
//do_stuff
}
This would also extend well to other classifications of class, like NonDeletable and NonEditable to allow for more fine grained behaviour.
Here is super short workaround, make your method final and start it with:
if(self::class!=static::class) return;#or throw an error
It will not prevent inheritance itself, but methods will not work in children classes (with error or without - is up to you).
As of PHP 5.4, you can use Traits.
For example, you could make a base class that only includes the methods that all child classes have:
class EntityManager {
public function create() {/*...*/}
public function retrieve() {/*...*/}
}
Then you could define a couple of traits:
trait EditTrait {
public function edit() {/*...*/}
}
trait DeleteTrait {
public function delete() {/*...*/}
}
You would then create an immutable child class like this:
class LogManager extends EntityManager {
...
}
And a mutable child class like this:
class ContactManager extends EntityManager {
use EditTrait;
use DeleteTrait;
...
}
Traits have some advantages over some of the other solutions here such as:
No duplication of code.
Single base class.
Methods that don't work or don't make sense, don't appear on classes that don't support them (especially important for docs and apis).
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.