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"
7
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.
2