general inheritance (not just) in PHP - php

Let's have this class
class A {
protected static function ident() { return "I am A"; }
public static function say() { return "I say '".self::ident()."'!"; }
}
Then I need to extend class A and override the ident() like this
class B extends A {
protected static function ident() { return "I am B"; }
}
Now when B::say(); is called, the result is I say 'I am A'. Is there any technique how to force it to produce I say 'I am B' without overriding the say() method? (Please don't ask me why to do this, just trust me it is reasonable in my project)
I believe it is possible via abstract class or interface, but I can not figure out how. If it is impossible in PHP, is there any language (except Haskell) which implements this feature?

Since PHP 5.3 late static bindings are available. You shouled take a look at that.
http://php.net/manual/en/language.oop5.late-static-bindings.php

say() is a static method, this kind of method belong to the class, not to an instance, it's not really inherited. If you want to create your own method you have to "override it" (but again it's not overriding).

Related

Objective C Categories Equivalent In PHP

Is there any chance there is an equivalent of Objective C Categories in PHP?
If all you want to do is break a huge class definition up over multiple files, and it's your class, then you can do that with traits. Just define some of the methods in a trait in a different file and use it in your class:
trait FooBar_ExtraMethods {
function foo () { return 'qux'; }
}
class FooBar {
use FooBar__ExtraMethods;
function bar () { return 'baz'; }
}
But if you want to add methods to somebody else's class, then there's simply no way to do that with vanilla PHP. Your choices are:
Live with the fact that this isn't possible and just write a function that takes instances of the class instead of extending it.
Use an extension to add the functionality into the language. Right now, the only contender is Dmitry Zenovich and Sara Golemon's Runkit. Zenovich's fork currently seems to be better-maintained and generally superior to Golemon's (although Golemon's is the one hosted on PECL), and the instructions below use Zenovich's fork.
Suppose I have an existing user-defined class Foo...
class Foo {
function methodA($arg) { return 2*$arg; }
}
I can add a method to it like this:
runkit_method_add('Foo', 'methodC', function ($arg) {
return 5 * $this->methodA($arg);
});
and call it like an ordinary method:
$f = new Foo;
echo $f->methodC(2); // 20
A couple of caveats:
You can't add methods to built-in classes. So if you want to use this to extend library-defined classes, you're good, but if you want to extend built-in classes like DateTime, you're out of luck.
This isn't remotely idiomatic - indeed, Runkit's tagline is "For all those things you.... probably shouldn't have been doing anyway.....". I leave it to your judgement whether to let that deter you from doing it.
It looks like a trait.
trait CarMaintenance{
public function needsOilChange(){}
public function changeOil(){}
public function rotateTires(){}
public function jumpBatteryUsingCar(){}
}
class Car {
use CarMaintenance;
public function startEngine() {}
public function drive() {}
public function turnLeft() {}
public function turnRight() {}
}
But traits could be reused in other class and could have their own hierarchy tree.

Alternative model for PHP abstract static class methods

Ok, so I've read lots of posts on here about this, but I think this is a specific and new question.
I want the functionality of what lots of us on here wrongly call an "abstract static method". That is: I want a class that insists classes that extend it implement certain static methods.
It seems there are two roads round the much discussed problem of not allowing abstract static, but both seem inelegant.
Problem
The following generates an error: "PHP Strict Standards: Static function A::fn() should not be abstract".
<?php
abstract class A
{
abstract static public function fn();
}
class B extends A
{
static public function fn()
{
// does something on class vars etc.
}
}
Solution 1: use Interfaces
<?php
interface iA {
static function fn();
}
abstract class A implements iA
{
} // obviously this would have other stuff in it in reality
class B extends A
{
static public function fn()
{
// does something on class vars etc.
}
}
The problem with this is that an interface assumes (dictates) that all the methods be public. So while this achieves the goal of insisting that sub-classes of an abstract class have certain static methods, it can only be used for public methods; there is still no way to ensure subclasses of A implement a protected static method.
Protected static methods are useful when the method works entirely on static data but ought not to be called from 'outside'.
Solution 2: exceptions
abstract class A
{
static public function fn()
{
throw new Exception(get_called_class() . " must implement fn()");
}
}
class B extends A
{
static public function fn()
{
// does something on class vars etc.
}
}
This works at runtime if fn() when called. But it's not useful to have to deal with coding syntax mistakes at runtime. And while this could be a hack for one method, it's a lot more code for each method.
Is there something so wrong with this design that the language rightly forbids it? Seems odd that there are various ways to insist subclasses provide most types of method, but not static ones.
It's because static methods belong to the class where they are defined. A::fn() and B::fn() are two different methods, regardless of the inheritance tree. So it makes little sense to define A::fn() as abstract.
Maybe your methods in question should not be abstract at all? If you want to use any kind of polymorphism, there should be objects involved.
I might be totally wrong, but I have no problem in using
abstract class A
{
abstract static public function fn();
}
class B extends A
{
static public function fn()
{
print 1;
}
}
B::fn();
It produces 1 as an output. I have run your code in here. What version of php do u use ?

Is passing $this to a static method tight coupling?

Here is a simple example:
class Class_A {
protected $_property;
public function method()
{
Class_B::method($this);
}
public function getProperty()
{
return $this->_property;
}
}
class Class_B {
public static function method(Class_A $classA)
{
$classA->getProperty();
}
}
$classA = new ClassA();
$classA->method();
Is it ever okay to pass $this as a parameter to the method of another class? Or is that always going to be tight coupling? I could pose another similar example using a Factory Pattern in place of the static method call.
It depends on the exact behaviour of Class_A and Class_B, but in general it would probably be better to define an interface which is implemented by Class_A and type hint for that. The methods of Class_A that are required by Class_B (e.g. getProperty()) should appear in your interface. Then, if you want to switch Class_A with another class at a later date, all it has to do is implement the same interface.
Yet again, it depends on the behavior of the classes in question, but if there was another Class_C for example that also used Class_B 's static method you might want to consider having Class_A and Class_C extend Class_B. More information can be found on the php object inheritance page.

What is the purpose of the initial function in a PHP class which has the same name as the class?

I am getting started with OO PHP, and after reviewing a variety of classes which I have downloaded from the internet, I have noticed that some - but not all - of these classes have an intial function with the same name e.g.
class MyClass{
function MyClass{
//function contents in here
}
function otherfunction{
//more stuff here
}
}
What is this inital function for? And how does it help with writing classes?
It's an old-style constructor. If you are using PHP 5 (you ought to), you should avoid those constructors and do instead:
class MyClass{
function __construct() {
//function contents in here
}
function otherfunction() {
//more stuff here
}
}
Constructors are, in short, used to run initialization code and enforce class invariants.
it is a constructor - anything put in here is executed when the object is instantiated
That function is a constructor. It is used for initializing the object.
Constructor
please also note that it's case insensitive. For example whan you have a Bark() class for a dog game the class name Bark is your reference to the noise that a dog makes.
If you want a specifig dog (e.g. a poodle which extends a general Dog pbject) to bark, you could name that method bark(), because that's what you want the dog to do (see the duality between the THING and the COMMAND ? (Bark class and bark() method) ).
So, when you do this:
interface BarkBehaviour
{
public function bark();
}
class Bark implements BarkBehaviour
{
public function bark()
{
echo "\nWoof!";
}
}
the instantiation of the barkBehaviour property of your dog will echo "Woof", because PHP thinks that the bark() method is the constructor for the Bark class, which you did NOT intend that way. In JAVA these things are case sensitive so the Bark classes constructor must be called Bark(), not bark().

PHP Import Foreign Class' Method into MyClass

Wondering if this is possible in PHP Land:
Let's say I have a class as follows:
class myClass{
var $myVar;
...
myMethod(){
$this->myVar = 10;
}
}
and another class:
class anotherClass {
...
addFive(){
$this->myVar += 5;
}
}
The 'anotherClass' is 3500 lines long and I just want the single 'addFive' method to use in myClass.
Is there a way I can import the function and be able to call it in my class and the $this would reference the myClass object?
Is this good/bad practice?
(optional) How does this work in Python? (Just curious as I'm starting to learn Python)
The easiest way to do this is have one class extend the other
class myClass extends anotherClass {
}
The myClass class now has access to all the methods of anotherClass that are public or protected.
If you only want the class to have one method of the other, or it's not practical to have one class extends from the other, there's nothing built into PHP that will allow you to do this. The concept you're looking to Google for is "Mixin", as in Mix In one class's functionality with another. There's an article or two on some patterns you could try to achieve this functionality in PHP, but I've never tried it myself.
Good idea/Bad Idea? Once you have the technique down it's convenient and useful, but costs you in performance and makes it harder for a newcomer to grok what you're doing with your code, especially (but not limited to) someone less familiar with OO concepts.
A better approach would be to move the complex method into its own class. Then both of your classes can instantiate it, pass any necessary data, and call the method.
If your myClass extends anotherClass it inherits all the methods and properties of anotherClass (except those marked private).
class AnotherClass {
protected $myVar;
public function addFive(){
$this->myVar += 5;
}
}
class MyClass extends AnotherClass {
public function __construct() {
$this->myVar = 0;
}
public function myMethod(){
$this->myVar = 10;
}
}
$m = new MyClass;
$m->myMethod();
$m->addFive();
var_dump($m);
prints
object(MyClass)#1 (1) {
["myVar":protected]=>
int(15)
}

Categories