I have this Base class:
class Base
{
public $extA;
public $extB;
function __construct()
{
}
public function Init()
{
$this->extA = new ExtA();
$this->extB = new ExtB( $this );
}
public function Test()
{
return 'Base Test Here!';
}
}
class ExtA extending the Base Class
class ExtA extends Base
{
public function Test()
{
return 'ExtA Test Here!';
}
}
class ExtB extending the Base Class too
class ExtB extends Base
{
private $base;
public function __construct( $base )
{
$this->base = $base;
}
public function Test()
{
return 'ExtB calling ExtA->Test()::' . $this->base->extA->Test();
}
}
$base = new Base();
$base->Init();
var_dump( $base->Test() );
var_dump( $base->extA->Test() );
var_dump( $base->extB->Test() );
I try to call the ExtA class Test() function from the ExtB,
both of ExtA and ExtB is exnteding the Base class.
My question is : is this ok, or have a better, faster solution for this?
The extends is necessary too?
Or simply enough like this
class ExtA
{
...
}
class ExtB
{
...
}
Thanks!
This is weird way of OOP.
The Base class should not know anything about its children so we shall go more correct way. Let's implement Decorator pattern:
interface IExt
{
public function test();
}
abstract class ExtDecorator implements IExt
{
protected $instance;
public function __construct(IExt $ext)
{
$this->instance = $ext;
}
}
class ExtA extends ExtDecorator
{
public function test()
{
return 'ExtA::test here and calling... ' . $this->instance->test();
}
}
class ExtB extends ExtDecorator
{
public function test()
{
return 'ExtB::test is here and calling... ' . $this->instance->test();
}
}
class Base implements IExt
{
public function test()
{
return 'Base::test here!';
}
}
class Printer
{
public static function doMagic(IExt $ext)
{
echo $ext->test()."\n";
}
}
Printer::doMagic($base = new Base);
// Base::test here!
Printer::doMagic($extA = new ExtA($base));
// ExtA::test here and calling... Base::test here!
Printer::doMagic(new ExtB($extA));
// ExtB::test is here and calling... ExtA::test here and calling... Base::test here!
You can play further any way you want
Related
I have some classes:
class A{
public $D;
public function __construct()
{
$this->D = new D();
}
}
class C extends E{
public function testC(){
return 'test C';
}
}
class B extends A
{
public function __construct()
{
$this->C = new C();
}
public function testB()
{
echo $this->C->testC();
}
}
(new B)->testB();
I would like transfer variables class A to class C, how i can make it (that i can use variables class A in class C) ?
What you want to achieve is most likely this.
class A
{
public $variable;
}
class B extends A
{
public function __construct()
{
$this->variable = 'value';
}
public function testVar()
{
echo $this->variable;
}
}
I suggest reading OOP basics, there is much more to it than this.
interface A
{
public function method1();
public function method2();
}
abstract class B implements A
{
public $publicc = 2;
public function method1()
{
echo "in method1 of B<br>";
}
}
class C extends B
{
public $publicc = 4;
public function __construct()
{
}
public function method2()
{
}
public function method1()
{
echo $this->publicc + parent::$publicc; // error for using parent::$publicc
}
}
$obj = new C();
$obj->method1();
But php throws error echo $this->publicc + parent::$publicc. I just want to get parent class $publicc property directly that has value 2, Without using any accessor method. Is there a way to do this in php?
It depends on what publicc exactly holds but a constant might suit your needs?
interface A
{
public function method1();
public function method2();
}
abstract class B implements A
{
const PUBLICC = 2;
public function method1()
{
echo "in method1 of B<br>";
}
}
class C extends B
{
const PUBLICC = 4;
public function __construct()
{
}
public function method2()
{
}
public function method1()
{
echo self::PUBLICC + parent::PUBLICC; // error for using parent::PUBLICC
}
}
$obj = new C();
$obj->method1();
I think you want a static property. If it is a property you want to access without an instance, that usually indicates a candidate for a static variable.
abstract class B implements A
{
protected static $publicc = 2;
...
}
class C extends B
{
public $publicc = 4;
public function __construct()
{
}
public function method2()
{
}
public function method1()
{
echo $this->publicc + parent::$publicc; // error for using parent::$publicc
}
}
I would like to write a generic method that refers to a generic class (but the same method) in php.
class A {
public static function Dox(){
}
}
class B {
public static function Dox(){
}
}
class C{
public static function Include($class){
$result = $class::Dox(); //instead of 2 methods => A::Dox and B::Dox
}
}
I get an error.
any suggestions?
include is a keyword. Rename your method to foo(), bar() or anything that is not a keyword.
e.g.
<?php
class A {
public static function Dox() { return 'A::Dox'; }
}
class B {
public static function Dox() { return 'B::Dox'; }
}
class C {
public static function foo($class) {
$result = $class::Dox();
echo 'result: ', $result, "\n";
}
}
foreach( array('A','B') as $c ) {
C::foo($c);
}
prints
result: A::Dox
result: B::Dox
Does call_user_func work?
class A {
public static function Dox() {
}
}
class B {
public static function Dox() {
}
}
class C {
public static function Include($class) {
$result = call_user_func(array($class, "Dox"));
}
}
Include keyword "spesific keyword".
Try it:
public static function IncludeXXX(){...}
this is my class:
class toyota extends car {
function drive() {
}
function break() {
}
}
class car {
function pre() {
}
}
Is there any way I can do so that when I run $car->drive(), $car->break() (or any other function in toyota), it would call $car->pre() first before calling the functions in toyota?
Yep. You could use protected and some __call magic:
class toyota extends car {
protected function drive() {
echo "drive\n";
}
protected function dobreak() {
echo "break\n";
}
}
class car {
public function __call($name, $args)
{
if (method_exists($this, $name)) {
$this->pre();
return call_user_func_array(array($this, $name), $args);
}
}
function pre() {
echo "pre\n";
}
}
$car = new toyota();
$car->drive();
$car->dobreak();
http://ideone.com/SGi1g
You could do the following, but I don't think that is what you want.
class toyota extends car {
function drive() {
$this->pre();
}
function break() {
$this->pre();
}
}
class car {
function pre() {
}
}
You may want to look into PHP specific magic methods. http://php.net/manual/en/language.oop5.magic.php
This will better done with the magic methods called __call()
public function __call($name, $arguments)
{
$this -> pre();
return $this -> $name($arguments);
}
What is this method? It overrides the default method call, so that preCall State can be invoked.
Your toyota class
class toyota extends car {
public function __call($name, $arguments)
{
$this -> pre();
return call_user_func_array(array($this, $name), $arguments);
}
function drive() {
}
function break() {
}
}
If you are using PHP5 (>=5.3.2), there is a solution that works with declaring all methods as private. This will enforce method call from single function call:
exec_method()
To run at: http://ideone.com/cvfCXm
The code snippet is here:
<?php
class car {
//method to get class method
public function get_method($method_name) {
$class = new ReflectionClass(get_class($this));
$method = $class->getMethod($method_name);
$method->setAccessible(true);
return $method;
}
public function exec_method($method_name, $arg_args=array()) {
//execute the pre() function before the specified method
$this->pre();
//execute the specified method
$this->get_method($method_name)->invokeArgs($this, $arg_args);
}
public function pre() {
echo 'pre';
echo '<br />';
}
}
class toyota extends car {
private function drive() {
echo 'drive';
echo '<br />';
}
private function brake() {
echo 'brake';
echo '<br />';
}
}
$toyota = new toyota();
$toyota->exec_method('drive');
$toyota->exec_method('brake');
?>
Reference:
Answer to Best practices to test protected methods with PHPUnit [closed]
Just add a constructor, like this...
class toyota extends car {
function __construct() {
$this->pre();
}
function drive() {
echo "drive!";
}
function dobreak() {
echo "break!";
}
}
class car {
function pre() {
echo "Hello!";
}
}
$car = new toyota();
$car->drive();
$car->dobreak();
Classes which have a constructor method call this method on each
newly-created object, so it is suitable for any initialization that
the object may need before it is used.
break is reserved, so you shouldn't use this as a function name.
I want to have a static method in a parent class that creates instances of whatever subclass i call this method on.
An example to make this more clear:
class parent {
public static method make_objects($conditions){
for (...){
// here i want to create an instance
// of whatever subclass i am calling make_objects on
// based on certain $conditions
}
}
}
class sub extends parent{
...
}
$objects = sub::make_objects($some_conditions);
As of php 5.3 you can use the static keyword for this
<?php
class A {
public static function newInstance() {
$rv = new static();
return $rv;
}
}
class B extends A { }
class C extends B { }
$o = A::newInstance(); var_dump($o);
$o = B::newInstance(); var_dump($o);
$o = C::newInstance(); var_dump($o);
prints
object(A)#1 (0) {
}
object(B)#2 (0) {
}
object(C)#1 (0) {
}
edit: another (similar) example
<?php
class A {
public static function newInstance() {
$rv = new static();
return $rv;
}
public function __construct() { echo " A::__construct\n"; }
}
class B extends A {
public function __construct() { echo " B::__construct\n"; }
}
class C extends B {
public function __construct() { echo " C::__construct\n"; }
}
$types = array('A', 'B', 'C');
foreach( $types as $t ) {
echo 't=', $t, "\n";
$o = $t::newInstance();
echo ' type of o=', get_class($o), "\n";
}
prints
t=A
A::__construct
type of o=A
t=B
B::__construct
type of o=B
t=C
C::__construct
type of o=C
I think you want something like this:
class parent {
public static function make_object($conditionns) {
if($conditions == "case1") {
return new sub();
}
}
}
class sub extends parent {
}
Now you can create an instance like this:
$instance = parent::make_object("case1");
or
$instance = sub::make_object("case1");
But why would you want all the sub classes to extend the parent? Shouldn't you much rather have a parent for your models (sub classes) and then a factory class, that creates the instances for this models depending on the conditions given?
Umm, wouldn't that be:
class sub extends parent {
public static function make_objects($conditions) {
//sub specific stuff here
//....
}
}
make the parent class an abstract class and make the parent method also an abstract
abstract static class parent {
abstract function make_method() {
// your process
}
}
class child extends parent {
public function __construct() {
parent::make_method();
}
}