Is there any possibility to reduce the access level of a function in a derived class in PHP?
example (... means more code)
class foo
{
public function myFunction() { ... }
public function myOtherFunction() { ... }
}
class bar extends foo
{
private function myFunction() { ... }
}
Now I should'nt be able to call MyFunc ion a bar object. But doing it this way doesn't seem to be valid in PHP. Any other way? I know I could implement an empty function but I don't want to expose the function in the interface at all.
Its not valid in OOP anyway. If you implement a public method, you promise, that this class and all children provides this functionality. To remove a public method means, that you break your promises ;) Because all public methods and properties define the interface of the class and breaking an interface is never a good idea.
Without any clearer information about what you are going to do I suggest to just throw an exception, something like "Not supported".
Related
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.
I'm trying to write an abstract class (or interface) which forces the extending class to implement a protected static function.
But this is neither possible with an abstract class nor an interface.
Errors:
static functions should not be abstract
access type for interface members must be omitted
Any ideas how to accomplish that?
UPDATE
The purpose is basically to call the public function statically. This way the class does not need to be instanciated.
It is also not necessary to make _doSpecificStuff() callable from class-external code.
abstract class Foo
{
public static function doStuff()
{
[generic code]
static::_doSpecificStuff();
}
// sth like that would be nice to have:
abstract static protected function _doSpecificStuff();
}
From a theoretical as well as a practical standpoint, there's no real need to declare a static method abstract.
Abstract methods are there to have a child class fill in a blank. That's typically because the parent class (the original abstract class) does some generic operation, but can/must be adapted to certain specific situations and can thus force child classes to implement only this particular variable part in the otherwise generic algorithm. Abstract methods are supposed to be a blank spot within a larger algorithm.
A parent method would call implementations of its abstract methods without knowing or caring who implements them or how they're implemented:
abstract class Foo {
public function someAlgo() {
$foo = $this->doSomethingSpecific();
...
}
abstract protected function doSomethingSpecific();
}
Foo doesn't care who or what fills in the blank doSomethingSpecific, it just relies on it being there and its signature, which abstract enforces. The specific object which implements this method or how it implements it is variable. This is important and is at the core of the issue.
Declaring a static method abstract is pretty useless in this scenario. Any static method can just as well be implemented as a non-static method, so there's no use for it here. If the class itself is supposed to call the abstract method as part of a larger generic algorithm as described above, there's no need for a static method.
So the only scenario left for a static method is for a public static method which is callable from anywhere:
abstract class Foo {
abstract public static function bar();
}
class Baz extends Foo {
public static function bar() { ... }
}
Baz::bar();
The thing is, since the abstract class Foo is not itself calling this function but this function is only called from external code, you're not really talking about a fill-in-the-blank method, you're talking about an interface. So, you should be using an interface instead.
But even there, since you have to type the specific class name in your source code, hardcoded, there's little point for an interface as well.
The point of declaring an interface or abstract method signature is that you want to fix the method signature so any code can call that particular method without caring what object it's calling it on in particular. But since you have to hardcode the class name, there's no variability in the object you're calling it on. If you type Baz::bar(), you know exactly what class you're calling what method on. Therefore there's little point in abstracting the interface/signature.
Compare:
interface FooInterface {
public function bar();
}
function baz(FooInterface $foo) {
$foo->bar();
}
The function baz can rely on its argument having a bar() method due to the interface declaration. The specific object that's implementing the method is irrelevant and will vary.
abstract class Foo {
public function someAlgo() {
$foo = $this->doSomethingSpecific();
...
}
abstract protected function doSomethingSpecific();
}
The class Foo can rely on it having the doSomethingSpecific method. The specific object that's implementing the method is irrelevant and will vary.
abstract class Foo {
abstract public static function bar();
}
class Baz extends Foo {
public static function bar() { ... }
}
Baz::bar();
What exactly are you relying on or abstracting here? You can be pretty darn sure Baz will have the method bar() every time, because you're only ever calling it on the same hardcoded class. Nothing is variable here.
Assuming that I have to create a class that takes some text do some processing and return it ... with no dependency and it's a stateless class..
I'd like to know would be better to create a stateless class without constructor or just create a static class (in php it's just Static methods)
class like this:
class ClassName
{
public function processText($text)
{
// Some code
$text = $this->moreProcessing($text);
return $text;
}
protected function moreProcessing($text)
{
return $text;
}
}
and this:
class ClassName
{
public static function processText($text)
{
// Some code
$text = static::moreProcessing($text);
return $text;
}
protected static function moreProcessing($text)
{
return $text;
}
}
I Know that dependency injection into the class where these classes are used would be better but assume that I just won't have dependency injection..
My question is mainly would it be better to create static class for the simple example above?
Practically you will see no difference whatsoever.
It's only in the syntax, and the ability of a constructor to perform stuff automatically, though you still have to create instances to invoke the constructor, which in this case is not far off calling some equivalent static member function.
However, non-static member functions are supposed to affect internal state so, if you have no state, static member functions seem more conventional, and will be slightly less surprising to users of the class.
The best approach, though, is to stick your functions in a namespace. Classes are for data and functions operating on that data... even static ones.
I have a set of independent functions which I want to put in a class.
They do not depend on any objects of the class, so while calling them, all the values required would be passed as arguments.
Is it fine if I declare all of them as static so that i can call them with just one command like className::functionName(argument1,argument2,...)
or do i keep them as normal public function and call them through a class object?
You can (but you shouldn't do it):
class YourClass {
public static function yourMethod( ) {
echo "method called";
}
}
YourClass::yourMethod();
The reason why you shouldn't do it is because when you use the static call in some other class / function / whatever you have tightly coupled the YourClass to the other class. hence you are making it pretty hard to do unit tests or simply switch to another moethod without going trhough all the code where it is used. And also don't forget you just added something globally.
You also say:
I have a set of independent functions which I want to put in a class.
This is a big code smell in my book. This makes it sound like your class violates the SRP principle in SOLID programming.
Hence I would just instantiate the class.
Let's see why it makes your code hard to test:
class SomeClassWithMethods
{
public static function doSomething()
{
}
}
class SomeClassYouWantToTest
{
public function doSomething()
{
return SomeClassWithMethods::doSomething(); // this is now tightly coupled and would be impossible to mock when unit testing it
}
}
Also that that SomeClassWithMethods::doSomething is now globally defined.
We like to call this the silver bullet :) :
Yes this is not bad.
You can define them as static functions and like you said - you can call them with just one statement.
class Foo {
public static function bar( ) {
echo "bar called";
}
}
I'm trying to create a PHP file that calls a function in another file. Some sample code:
Interface code:
interface AJAXDispatcher {
static function dispatch($action);
}
Implementation:
class myAJAX implements AJAXDispatcher {
static function dispatch($action) {
if ($action === "action1") {
do_something();
}
This seems ok to me. I try to call it by first importing the file that it's in. I'm trying to make it independent of the name of the class so that I can do something like this:
AJAXDispatcher::dispatch($action);
Thought this would work as myAJAX would inherit from AJAXDispatcher, but I get the following error:
Fatal error: Cannot call abstract method AJAXDispatcher::dispatch() in ....
Anyone know what I'm doing wrong?
Interfaces with static methods don't make any sense, because to call a static method you (usually) need to know the class name.
Instead, you should make the method non-static and create an instance of myAJAX somewhere. The code that calls the AJAXDispatcher receives the instance and calls it. You can use type hinting to ensure you are getting the right instance.
interface AJAXDispatcher {
public function dispatch($action);
}
class myAJAX implements AJAXDispatcher {
public function dispatch($action) {
do_something();
}
}
class Controller {
private $dispatcher;
public function __construct(AJAXDispatcher $dispatcher) {
$this->dispatcher = $dispatcher;
}
public function action($action) {
$this->dispatcher->dispatch($action);
}
}
$dispatcher = new myAJAX();
$controller = new Controller($dispatcher);
$controller->action('index');
This example uses the Dependency Injection design pattern.
An interface has no method implementation. It only defines a public API that classes have to implement. How they implement it, is up to the concrete classes. Thus, you cannot call methods of an interface directly, because there is no code to call. You have to call the method on the implementing class.
Have a look at the PHP Manual on Interfaces.
No, you can't do that. There are several things wrong here
That's now how inheritance works. Method chaining goes up the class hierarchy, now down.
Static methods are connected to the class. If you override a static method in a subclass, and want to invoke the subclass' version, you must reference the subclass explicitly.
Interfaces have no implementation. Even if the language allowed the type of call you're making, nothing would happen. AJAXDispatcher::dispatch() has no body.
You're going to have to re-think your strategy here.