0

Let me illustrate using the PHP language. The discussion here is, how should I do exactly to solve this problem in a clear and unambiguous mode.

Imagine that I have a class called Path. This class is responsible for defining an object that refers to a path of a file, for example. This class helps me with some tasks, for example:

$pathInstance = new Path("path/to/file.bin");
$pathInstance->exists();             // Return if file exists.
$pathInstance->get_dirname();        // Return the dirname of file.
$pathInstance->get_basename();       // Return the basename of file.
$pathInstance->is_file();            // So on...

However, there is a problem in this methodology when I need to, at the same time, use a static method that allows to perform a task without creating an instance. For instance:

When I call is_file() it'll check if the internal path if $this is refer to a file. But I want to do it too statically, for instance, Path::is_file("path/to/file.bin").

In PHP this is not recommended, and is required to make a basic workaround. And I personally think is not the right concept to be applied.


Imagine that I have it:

class Path {
    /** @var string */
    private $path;

    /** @param string $path */
    function __construct($path) {
        $this->path = $path;
    }

    /**
     * Normalize the path.
     * @param  boolean $force_normalize Force even if path doesn't exists.
     * @return string|false
     */
    public function normalize($force_normalize = null) {
        if($force_normalize === true) { /* ... */ }
        return realpath($this->path);
    }
}

So I use as:

$pathInstance = new Path("/abc/../def");
echo $pathInstance->normalize(); // output "/def"

But I would like to work TOO statically, for instance:

echo Path::normalize("/abc/../def"); // output "/def"
  • 4
    So what's the problem? – Robert Harvey Oct 9 '14 at 22:42
  • The first problem is that PHP does not allow it, in a natural way. The second is that there seems to be a better way. A method that acts as both static and non-static. Could cause trouble with arguments, for example. So I would like to know the best concept to solve the problem. For example: it would be the responsibility of the same class? Should set create a method static (as is_file_static) and instance method (as is_file)? Etc. – David Rodrigues Oct 9 '14 at 22:52
  • Is your only problem the notion that "this is not recommended" in PHP? And that you personally think it's not the right concept? If those two conditions didn't apply, would the static method be a suitable solution? I use static methods for this sort of thing in C# all the time and it has never been a problem (despite the TDD'ers assertions that static methods are somehow not testable). – Robert Harvey Oct 9 '14 at 22:54
  • I create a new example. I can't use $this in static methods on PHP (except with workaround). – David Rodrigues Oct 9 '14 at 23:05
  • 1
    To me the thing you want to do just feels dirty. If having a static method fits your use case, lift it out of the class and use it in a seperate class with static methods and remove it from your original class. – Pieter B Oct 10 '14 at 6:51
2

To me, this is a question of class design.

If we are designing for target implementation languages such as C++, Java, and the like (if you will allow them to be lumped together), the questions are

  • what use cases do you want to support?

  • how should their interfaces be structured?

  • how can those two masters be best supported and balanced?

You have given a requirement for the first question - you want static (class) methods and dynamic (instance) methods. For a given method, for now lets call these two methods classMethod and instanceMethod. We'll give them better names later.

For the second question, the interfaces to the two methods must be different. At present they have different names, but we would like them to be the same if they do the same job. What are the options?

  • We could put them in different classes, but that would just make our design more complex.

  • We could give them the same name, and then they'd need different parameter lists.

The second one is ideal for this problem. We can call our methods myMethod() for the instance method version, and myMethod(path) for the class version.

Regarding implementation, we could make our instance method call the class method, passing it's path. Or make the class method construct an instance and then call the instance method. Since I can see reasonable implementation alternatives, my high level class design job is done.

So as an implementer, my concerns will be

  • which approach is more natural in my target language?

  • do I want my implementation to match other implementations in other languages?

  • will there be obvious performance losses in choosing one implementation over another? (I say losses here, because while I wish to avoid premature optimization, I also want to avoid "deliberately inefficient" implementations).

Finally, given intuition that one implementation will not have a great advantage over the other, I would implement myMethod() to call myMethod(path).

Hope that helps.

  • 1
    The problem is just that PHP don't support real overloading. I could simulate it, but I'll have a conflict on PHPDoc. – David Rodrigues Oct 10 '14 at 3:55
  • 1
    Yes, not being a PHP expert I couched my answer in terms of C++, Java, and the like. In PHP we should just give these methods two different names, and call one from the other. – andy256 Oct 10 '14 at 4:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.