Can PHP Benefit From Partial Classes?

The concept of partial classes goes like this.

pc1.php


partial class PC {
public function first() {}
}

pc2.php


partial class PC {
public function second() {}
}

index.php


require 'pc1.php';
require 'pc2.php';

$pc = new PC;

$pc->first();
$pc->second();

Basically it lets you create a class from a few files.
This can be a very strong feature (that exists in other languages) because it’s probably one of the things that help team development the most.

Not to mention for frameworks it could be a key thing since it would make plugin creation very easy.

What do you think?

The concept of Partial Classes can be emulated in PHP by simply extending classes.

pc1.php

class Pc
{
    public function first()
    {

    }
}

pc2.php

class Pc_Partial extends Pc
{
    public function second()
    {

    }
}

index.php

require 'pc1.php';
require 'pc2.php';

$pc = new Pc_Partial;

$pc->first();
$pc->second(); 

Yes, I have been missing this kind of thing!

The concept of Partial Classes can be emulated in PHP by simply extending classes.

This is really not the same. Most important, the extended classname does not have the same name as the original class. Thus, you would have to go factory + inheritance, and the person who extends has to tell the factory to use another classname from now on.

A lot of interesting things can be done with delegation + magic methods. This means, you can define any mechanic you want to decide which code should be run for a method call. But, this adds a bit of mechanic overhead…

There is a proposal for traits (Which seems to be about the same thing as you’re suggesting). It probably won’t be in 5.3, but it may get accepted and included before 6.

Personally I’m not sure if I like it. I mean - From a theoretical standpoint is beautiful, but it’s also rather complicated to understand. I think perhaps allowing multiple inheritance and raise an error on conflict, would just be easier.

I think the traits are not as flexible as the partial classes mentioned above.

If you extend a class with partial classes, the final class does not need to know about where it is extended. With traits, you have to specify in the final class which “mixins” you want to use.

If you need this you can do it with __call(). In outline:

  • create a decorator stack class which holds whichever decorators you want to add
  • the decorator stack __call() looks through the stack for an object with the given method
  • the decorated object (which holds the decorator stack instance) __call() forwards unknown messages to the decorator stack

I’ll post the details if anyone is interested in seeing an example.

You don’t actually need any __call trickery, or traits etc, just to decorate an object although it could be useful if you specifically need the decorator methods to magically appear to be methods of the decorated object. To a client, it’s just a kind of syntactic sugar which cuts out calls to a middle-man.

Or is it more than that?

Sure you can do all kinds of decorators and delegates etc with magic methods. Or even without, if you don’t mind having these mechanics be visible in the interface.


$object->runOrDelegate('foo');  // no magic methods
$object->foo();  // magic method delegate

The delegates can be defined on static class level, or on object level, as you like.

However: All of this requires to implement this flexibility in the original class, or in the place where the class is used.

Not to mention for frameworks it could be a key thing since it would make plugin creation very easy.

If everything is a partial class by default (not sure if this is what the topic starter had in mind), then you don’t need to hope that the 3rd party thought about delegation flex points. You get it for free.

And even if not, then still a native support for partial classes will make such flexibility much cheaper. You will have a much higher chance that some 3rd party will implement native partial class features, than some home-baked magic method solution.

I could see myself using “method injection” occasionally (for example here) but I suspect it could also create a lot of bad design. At the moment, with everything in one class, you have to think hard how to cut the OOP cake. I’d be afraid that people will reach for traits too soon. Perhaps a coherent chunk of logic which really ought to be in one class could end up spread around the place in different traits.

I’d like this feature - it’s certainly helpful when internet speed/bandwidth is limited - put every function in a separate file, voila.

What I would like to see is import features, which I suppose could help in this situation:

<?php
class a{
    function someFunction() = import('somefunction.function.php');
}

That way you can do something like that but allow a single function, stored in one place, to be available in many classes without worrying about inheritance.

Another thing I’d like to see, similar to this is:

<?php
class myClass = import('/classes/myClass/');

Where ‘/classes/myClass/’ is a directory containing different parts of the class - it would load every file in the folder.

Many arguments (or an array) could be passed to it to glue multiple sections:

<?php
class myClass = import('/classes/myClass/', '/classes/base/');

It messes around with our current ideas of the OOP file system, but I think it could bring alot of much-needed flexibility to PHP applications.

@arkinstall

This can also be helpful to free the global namespace.
The file will not have any method name, it will only have the execution code. The filename can become the method name, but doesn’t need to: This is up to the programmer, and can be decided at runtime.
Typically, the files in one folder would represent the methods of one class. But again this is not necessary, any runtime hack can modify these rules.

I like how javascript allows to juggle around with functions and classes.

A problem I see is how to define the signature of a function, if all we have is a filename and the execution code? And what about object attribute variables? In fact the problem is not new, it’s the same with template files.

With PHP 5.3.0 we can mimic to some extent those features.

See this thread:

I don’t like it. It has far too much potential for abuse by unexperienced developers and to create code that would be a nightmare to debug. Do you really want to add the fun of “where is this method defined” to your already tedious debugging process?

In the meantime I still haven’t heard one single sound reason why this would be a good idea.

In the meantime I still haven’t heard one single sound reason why this would be a good idea.

Because .NET allows you to do it. :rolleyes:

Do java have partials too or only .Net have those ?

Well if you look at how it’s used in ASP.NET, the .aspx file (which is a hybrid of HTML and proprietry XML elements) together with a code-behind file form a partial class.

Your C# or VB code can then reference elements on the ASPX page as regular objects.

It helps to separate presentation and processing, and I personally find it a lot more intuitive than mashing HTML and inline code snippets in the one file.

Cheers,
D.

Yeah that’s one of its main uses in ASP.NET, but in big projects it really helps when classes can be partial. :slight_smile:

Last I checked, PHP doesn’t even support proper namespaces yet. Perhaps it should learn to crawl before we expect it to run?

Cheers,
D.

There’s no difference. Actually implementing partial classes would be much easier than to implement namespaces (which, by the way, are properly supported. Download 5.3 alpha 2 and see, it’s working great)

I can’t really comment on which would be easier to implement, having never written a programming language before. :slight_smile: Also, “properly supported” is not a phrase I’d use in reference to an unstable preview release.

Cheers,
D.

It’s unstable not because of the implementation of namespaces, but because of other things, so in reply to your first argument - either way, we have already learned how to crawl.

Partial classes are easier to implement since the parser would only have to add to the existing definition more. Namespaces have some harder to implement scoping features.