14

I'm trying to work out how to best complete my design work on my classes.

my situation.

i have an order abstract class that contains order methods and information that are required for 2 children classes

order_Outbound

and order_inbound

each child class requires 2 static public method called create and get

but from what i have read about php 5.3 you cant have abstract static methods ???

so my thought was to have an interface Order_Interface which takes over that role but how do i implement it. do i still implement it in the parent class

in which case the parent abstract class still requires me to create a get and create method within the abstract class. or do i implement it in the children and extend from the abstract class???

ALSO!!! both the outbound and inbound children require a create static method but require different parameters to be passed

can i in the interface have public static function create()

and in its implementation within order_outbound declare it public static function create($address, $reference, $orderID)

roguecoder
  • 187
  • 1
  • 2
  • 8
  • I don't see the code so it's just a guess but `Order::create()` and `Order::get()` probably shouldn't be static at all unless you've got some reasons to do them static. – Crozin May 13 '11 at 01:18
  • @Crozin - if you didn't want to use constructors for some reason, and wanted a method to create instances, you probably don't want to have to create an instance to call the instance-creation method. – Matt Mitchell May 13 '11 at 01:24
  • sorry yes that is exactly why i am doing it. the classes represent database records. my constructors are protected and use static methods to retrieve instances of the classes. – roguecoder May 13 '11 at 03:25
  • So let them represent database records and do nothing more. You should have separate object for retrieving data from database and populating it into objects. – Crozin May 13 '11 at 10:29

3 Answers3

15

In most languages, including PHP, you cannot require a class to implement static methods.

This means neither class inheritance, nor interfaces, will allow you to require all implementors define a static method. This is probably because these features are designed to support polymorphism rather than type definition. In the case of static methods you'll never have an object to resolve the type from, so would have to do ClassName::Method explicitly, so the theory is you wouldn't gain anything from polymorphism.

As such, I see three solutions

  1. Declaring the static methods in each class (after all, you are never going to

  2. If you want a method to create instances of your class, but don't want to require an instance to call this method, you could create "Builder" classes to serve this purpose (e.g. OrderBuilder), such that you instantiate an OrderBuilder and call the Create method on this object instead to get Order instances.

  3. (Recommended) Why aren't you simply using the Order constructor?

Matt Mitchell
  • 40,943
  • 35
  • 118
  • 185
  • in my database i have 2 tables. orderheader and orderbody. there are 2 kinds of orders outbound and inbound. i do not want the ability to simple create an instance of the object without there being a database record for it. so making the constructor protected and allowing people only to get an instance via either creating a new database record (order_outbound::create()) or retrieve a record thats already stored (order_outbound::get(id)). – roguecoder May 13 '11 at 03:30
  • because i never intend on these 2 classes being extended, is your suggestion just to ignore the interface and abstract class and just enter the static methods into each class individually without there being a upper level Forcing me to? – roguecoder May 13 '11 at 03:31
  • I'd say if you don't want to use a constructor then yeah go with the static methods, and don't get hung up on the "upper level forcing" bit. – Matt Mitchell May 13 '11 at 03:35
  • 1
    thanks for the help. its my first time designing such a large and complex system involving so many different classes. trying to figure out how they should all work together has been a major challenge. but an interesting one. – roguecoder May 13 '11 at 04:05
  • 1
    This answer is incorrect. Interfaces and abstract classes can require descendants to implement static methods. – tvanc May 13 '19 at 18:31
7

PHP 7.4+ allows to require a static method in an interface:

interface StaticInterface {
    public static function interfaceMethod();
}

class MyProvider implements StaticInterface {
    //public static function interfaceMethod() {}
}

Fatal error without the method: https://3v4l.org/YbA4u

No errors when implementing the method: https://3v4l.org/QNRJB

sun
  • 991
  • 9
  • 13
  • It obvously works, but there is no reference of allowing a static method in an interface on the official doc, isn't it ? – Neekobus Oct 20 '22 at 09:08
5

Update

After the comment from @hvertous, I decided to test this out. Using 3v4l we can see that abstract public static method:

  • Works for versions 5 > 5.1.6
  • Doesn't work for 5.2 > 5.6.38
  • Works for 7.0.0 > 7.3.1

Which confirms that it was removed in PHP 5.2, but if you are using PHP 7+ you can once again use abstract static methods.

Original answer

Yes, abstract static methods were removed in PHP 5.2. Apparently they were an oversight. See Why does PHP 5.2+ disallow abstract static class methods?.

However, you can have static methods in an interface, see this comment on php.net.

The problem you face is that you want your implementations to have different function signatures, which means that you probably shouldn't be using inheritance to solve your problem.

Yep_It's_Me
  • 4,494
  • 4
  • 43
  • 66