php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #53081 why you should bring back abstract static methods
Submitted: 2010-10-16 06:55 UTC Modified: 2010-10-16 19:42 UTC
From: giorgio dot liscio at email dot it Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 5.3.3 OS:
Private report: No CVE-ID: None
 [2010-10-16 06:55 UTC] giorgio dot liscio at email dot it
Description:
------------
hi, i really can not understand why this was dropped, but imagine this code

please read carefully and please examine my request before trash it

abstract class FSItem
{
      // abstract static method:
      abstract protected function isPathValid($path);

      protected function __construct($path){}

      // random per-item singleton
      public static function getByPath($path)
      {
            if(static::isPathValid($path)) // here is the static method call of classes. i want to check the path before instance it
                  return new static($path);
      }
}

class Dir extends FSItem
{
     //implementation:
     protected function isPathValid($path)
     {
          return is_dir($path);
     }
}

class File extends FSItem
{
     //implementation:
     protected function isPathValid($path)
     {
          return is_file($path);
     }
}

class Image extends File
{
     //implementation:
     protected function isPathValid($path)
     {
          return (bool)getimagesize($path);
     }
}

php changelog says: 

Dropped abstract static class functions. Due to an oversight, PHP 5.0.x and 5.1.x allowed abstract static functions in classes. As of PHP 5.2.x, only interfaces can have them. 

oversight what? it is a logical error? technical limitation?

thank you


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-10-16 06:58 UTC] giorgio dot liscio at email dot it
sorry, corrected code:

abstract class FSItem
{
      protected function __construct($path){}

      // random per-item singleton
      public static function getByPath($path)
      {
            if(static::isPathValid($path)) // here is the static method call of classes. i want to check the path before instance it
                  return new static($path);
      }

      // abstract static method:
      abstract protected static function isPathValid($path);
}

class Dir extends FSItem
{
     //implementation:
     protected static function isPathValid($path)
     {
          return is_dir($path);
     }
}

class File extends FSItem
{
     //implementation:
     protected static function isPathValid($path)
     {
          return is_file($path);
     }
}

class Image extends File
{
     //implementation:
     protected static function isPathValid($path)
     {
          return (bool)getimagesize($path);
     }
}
 [2010-10-16 07:15 UTC] rasmus@php.net
-Status: Open +Status: Bogus
 [2010-10-16 07:15 UTC] rasmus@php.net
A static method belongs to the class, not to an instance of that class and since 
you can't have an instance of an abstract class, static methods make no sense in 
abstract classes.  It is really that simple.
 [2010-10-16 07:21 UTC] rasmus@php.net
Sorry, I re-read that explanation, that didn't make sense.  I meant to say that 
methods in an abstract class require that any instance of that class implement 
those methods, but static methods belong to the class, not an instance.  You can't 
call methods from an abstract class, you can only call them in instances of that 
class, but static methods by definition belong to the class, but since you can't 
call methods in an abstract class you could never call these static methods so 
there is no point in them being there.
 [2010-10-16 08:15 UTC] giorgio dot liscio at email dot it
hi Rasmus, what an honor!

can you please give me some example code?

you are saying that self:: points to an abstract not-implemented method?

for example:

abstract class cA
{
      static function A(){self::B();}
      abstract static function B();
}


in this case can be thrown an error, but using static:: the call refers to the called class method, not the declaring class

static function A(){static::B();}

so it can be re-enabled in this case, no?

in php static methods are really powerful unlike java's, c#'s, don't limit them!

why interfaces allows static abstract methods? how self:: is resolved?
 [2010-10-16 08:27 UTC] rasmus@php.net
No, you are calling a method in an abstract class.  The fundamental characteristic 
of an abstract class is that you cannot call methods in them.
 [2010-10-16 08:36 UTC] giorgio dot liscio at email dot it
i know, but:

abstract class cA
{
      //static function A(){self::B();} error, undefined method
      static function A(){static::B();} // good
      abstract static function B();
}

class cB extends cA
{
    static function B(){echo "ok";}
}

cB::A();
 [2010-10-16 08:43 UTC] rasmus@php.net
Right, that is exactly how it should work.
 [2010-10-16 08:45 UTC] giorgio dot liscio at email dot it
but it is not allowed :(
 [2010-10-16 08:48 UTC] rasmus@php.net
What's not allowed?


abstract class cA {
      static function A(){static::B();}
      abstract static function B();
}

class cB extends cA {
    static function B(){echo "ok";}
}

cB::A();


This works fine.  You obviously can't call self::B(), but static::B() is fine.
 [2010-10-16 08:55 UTC] giorgio dot liscio at email dot it
so this:

Dropped abstract static class functions. Due to an oversight, PHP 5.0.x and 5.1.x allowed abstract static functions in classes. As of PHP 5.2.x, only interfaces can have them.

is not valid no more in 5.3?
 [2010-10-16 09:01 UTC] giorgio dot liscio at email dot it
i'm investigating about my error

Static function FSItem::ensurePathIsValid() should not be abstract
 [2010-10-16 09:27 UTC] giorgio dot liscio at email dot it
ok it is a php bug, it is related to files and namespaces... 

if you put this in global space works (no error triggered)

<?php
// index.php
ini_set("display_errors", true);
ini_set("error_reporting", E_ALL | E_STRICT);
require("FSNuovo/Directory.php");
?>


<?php
// FSNuovo/Directory.php
namespace FSNuovo;
abstract class AbstractFileSystemItem
{
	abstract static function ensurePathIsValid($fullPath);
}
class Dir extends AbstractFileSystemItem
{
	static function ensurePathIsValid($fullPath){}
}
?>
 [2010-10-16 09:37 UTC] giorgio dot liscio at email dot it
no more a change request

http://bugs.php.net/bug.php?id=53082

bug reported

thank you Rasmus!
 [2010-10-16 19:39 UTC] giorgio dot liscio at email dot it
so, felipe says that is not a bug and hes right

rasmus you say that this code is correct, but i still get a strict warning

abstract class cA {
      static function A(){static::B();}
      abstract static function B();
}

class cB extends cA {
    static function B(){echo "ok";}
}

cB::A();
 [2010-10-16 19:42 UTC] rasmus@php.net
Which strict warning do you get?  I don't see one.
 [2010-10-16 20:23 UTC] giorgio dot liscio at email dot it
Strict Standards: Static function cA::B() should not be abstract in ..\www\index.php on line 6

5.3.3
 [2010-10-17 02:03 UTC] cmanley at xs4all dot nl
This bug (emitting E_STRICT for abstract static methods in PHP 5.3 while static 
inheritance has finally been implemented) leads to another bug that I recently 
submitted: http://bugs.php.net/bug.php?id=53086
These are definately different bugs, but this bug spawns the other one which is 
more catestrophic.

If you don't see the bug, then add E_STRICT to your error reporting:
error_reporting(E_ALL | E_STRICT);
 [2010-10-17 02:56 UTC] giorgio dot liscio at email dot it
simplified case

abstract class AFSItem
{
     public static function                getIfValid   ($fullPath)
     {
          // i use static::isValid to get the method defined in the called class
          if(static::isValid($fullPath)) return new static($fullPath);
     }
     protected function                    __construct  ($fp){}

     // i want to force real classes to implement a way to check a path before instance an object
     protected abstract static function    isValid      ($fullPath); // abstract declaration
}

class File extends AFSItem
{
     protected static function             isValid      ($fullPath)  // implementation
     {
         return is_file($fullPath);
     }
}

class Dir extends AFSItem
{
     protected static function             isValid      ($fullPath)  // implementation
     {
         return is_dir($fullPath);
     }
}

class Image extends File
{
     protected static function             isValid      ($fullPath)  // implementation with override
     {
         if(parent::isValid($fullPath) AND (bool)getimagesize($fullPath)) return true; return false;
     }
}
 [2010-10-17 13:59 UTC] cmanley at xs4all dot nl
Georgio,
Your example makes perfect sense. I just wish the bug handlers wouldn't be so rude 
as to flag valid reports as bogus when users spend effort to report these bugs 
with examples.

There's nothing bad about having abstract static methods in a language that 
finally supports static inheritance (since PHP 5.3). This is normal practice in 
other languages too so E_STRICT shouldn't be emitted.
 [2010-10-20 16:47 UTC] giorgio dot liscio at email dot it
i know... could someone analyze my request please? i know that a lot of bug reports are bogus, but not all
 [2010-11-14 19:10 UTC] giorgio dot liscio at email dot it
...
 [2012-01-19 18:20 UTC] andy at andy-burton dot co dot uk
Still get strict warning in 5.3.2 - static abstract classes in 5.3 make perfect 
sense to me, no idea why this is flagged as bogus!
 [2013-01-08 23:18 UTC] jon at langevin dot me
Valid issue, please re-classify as a bug. This is not a feature request.
 [2013-05-09 17:27 UTC] keith at madsync dot com
"abstract" means required implementation by subclasses, "static" means declared on the class.  ignoring the internals of php's construction for a moment, and how difficult proper implementation of the feature might be, these are orthogonal concepts. "abstract static function X" means "classes extending this one must declare static method X."  

right now in order to enforce a static contract, i have to use an interface *and* an abstract class.  this means more code and more distributed functionality in my codebase. worse, i have to remember to implement the interface on every child class, which almost defeats the purpose of having the interface in the first place - "class A extends Letter implements IAlphabet + abstract class Letter" rather than "class A extends Letter + abstract class Letter implements IAlphabet." and the only purpose of IAlphabet is to enforce that A contains some static method?  ugh.  that should be Letter's job, it's why i made it abstract in the first place.

allowing static and abstract to work together as the orthogonal concepts they are leads to simpler, more readable, better-distributed code, and doesn't require i instantiate objects for functionality not related to object state.  the fact that the static method on the parent class is not a part of the child's inheritance seems to me irrelevant.  please include this feature again in future releases.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 20:01:28 2024 UTC