I'm reading Programming Scala. At the beginning of chapter 4, the author comments that Java supports static methods, which are "not-so-pure OO concepts." Why is this so?
One reason that static methods aren't very OO that hasn't been mentioned so far is that interfaces and abstract classes only define non-static methods. Static methods thus don't fit very well into inheritance.
Note also that static methods do not have access to "super
", which means that static methods cannot be overridden in any real sense. Actually, they can't be overridden at all, only hidden. Try this:
public class Test {
public static int returnValue() {
return 0;
}
public static void main(String[] arg) {
System.out.println(Test.returnValue());
System.out.println(Test2.returnValue());
Test x = new Test2();
System.out.println(x.returnValue());
}
}
public class Test2 extends Test {
public static int returnValue() {
return 1;
}
}
When you run this, you won't get what you expect. Test.returnValue()
gives what you expect. Test2.returnValue()
hides the method of the same name in the superclass (it does not override it), and it gives what you would expect.
One might naively expect "non-statically" calling a static method to use polymorphism. It doesn't. Whatever class the variable is declared as is the one used to look up the method. This is bad form because someone might expect the code to do something different from what it actually does.
This doesn't mean, "Don't use static methods!" It does mean that you should reserve use of static methods for those instances where you really want the Class object to own the method, and not just as a lazy way of making a singleton.
Object-orientation is about three things:
- messaging,
- local retention and protection and hiding of state-process, and
- extreme late-binding of all things.
Of those three, the most important one is messaging.
Static methods violate at least messaging and late-binding.
The idea of messaging means that in OO, computation is performed by networks of self-contained objects which send messages to each other. Sending a message is the only way of communication/computation.
Static methods don't do that. They aren't associated with any object. They really aren't methods at all, according to the usual definition. They are really just procedures. There's pretty much no difference between a Java static method Foo.bar
and a BASIC subroutine FOO_BAR
.
As for late-binding: a more modern name for that is dynamic dispatch. Static methods violate that, too, in fact, it's even in their very name: static methods.
Static methods break some very nice properties of object-orientation. For example, object-oriented systems are automatically capability-safe with objects acting as capabilities. Static methods (or really any statics, be that static state or static methods) break that property.
You can also execute every object in parallel in its own process, since they only communicate via messaging, thus providing some trivial concurrency. (Like Actors, basically, which shouldn't be too surprising, since Carl Hewitt created the Actor Model based on Smalltalk-71, and Alan Kay created Smalltalk-71 partially based on PLANNER, which in turn was created by Carl Hewitt. The close relationship between actors and objects is far from coincidental, in fact, they are essentially one and the same.) Again, statics (both static methods, and especially static state) break that nice property.
Don't confuse "not-so-pure OO concepts" with "bad practice". Being "pure OO" is not some panacea that you should attempt to achieve. Just because static methods don't take an instance variable as a parameter does not mean that they are not useful. Some things just don't lend themselves to objects, and they should not be forced into that mold just for the sake of "purity".
Some people think that things should be "pure", and thus anything "impure" is bad practice. In reality, bad practice is just doing things that are confusing, hard to maintain, difficult to use, etc. Creating static methods that take an instance is bad practice because any method that takes an instance should probably be an instance method. On the other hand, things like utility and factory functions generally don't take an instance, so they should be static.
If you're wondering why they're not "pure OO", it's because they are not instance methods. A "pure" OO language would have everything being an object and all functions be instance methods. Of course, that's not terribly useful all the time. For example, consider the Math.atan2
method. It takes two numbers and doesn't require any state. What object could you even make it a method of? In a "pure" OO language, Math
might itself be an object (a singleton, probably), and atan2
would be an instance method, but since the function doesn't actually use any state in the Math
object, it is also not a "pure OO" concept.
atan2
function measures the radians of the angle of a single point to the positive x-axis. In other words, it shouldn't take two number arguments in the first place, it should take a single point argument. Which, in OO terms, could be modeled as a method on a point object. –
Crosslet stdev
and average
functions? Should those be methods of Array
? Or should they be instance methods of their own class (Stats
) that holds all the numbers such that you have to convert your Array
to a Stats
so you can average them? Or should they be static methods that you simply pass an array of numbers to? –
Curvature One reason that static methods aren't very OO that hasn't been mentioned so far is that interfaces and abstract classes only define non-static methods. Static methods thus don't fit very well into inheritance.
Note also that static methods do not have access to "super
", which means that static methods cannot be overridden in any real sense. Actually, they can't be overridden at all, only hidden. Try this:
public class Test {
public static int returnValue() {
return 0;
}
public static void main(String[] arg) {
System.out.println(Test.returnValue());
System.out.println(Test2.returnValue());
Test x = new Test2();
System.out.println(x.returnValue());
}
}
public class Test2 extends Test {
public static int returnValue() {
return 1;
}
}
When you run this, you won't get what you expect. Test.returnValue()
gives what you expect. Test2.returnValue()
hides the method of the same name in the superclass (it does not override it), and it gives what you would expect.
One might naively expect "non-statically" calling a static method to use polymorphism. It doesn't. Whatever class the variable is declared as is the one used to look up the method. This is bad form because someone might expect the code to do something different from what it actually does.
This doesn't mean, "Don't use static methods!" It does mean that you should reserve use of static methods for those instances where you really want the Class object to own the method, and not just as a lazy way of making a singleton.
Static methods cause tight coupling, which is a violation of good Object Oriented Design. The tight coupling of the calling code and the code within the static method cannot be avoided through Dependency Inversion because static methods inherently don't support object-oriented design techniques such as Inheritance and Polymorphism.
Besides static methods are difficult to test because of these tightly-coupled dependencies, which oftentimes lead to third-party infrastructure that the code depends upon - like a database, and it makes it very difficult to change the behavior without actually going in and changing the code.
Static methods aren't considered good OO practice due to below reasons:
1) Prevents from Re-usability:
Static methods can't be overriden. It can't be used to in interface.
2) Object Lifetime is very long:
Static methods remain in the memory for a log time and its garbage collection takes long time. Developer's don't have control on destroying or creating of Static variables. Excessive usage of static variables can result in the memory overflow.
3) Also, some other points:
It doesn't respect the encapsulation because object does't remain in the complete control of its state. It doesn't follow concepts like Inversion of control, loose coupling, dependency injection, etc.
Static methods are not so pure OO concepts because they can be invoked without an object actually being associated with them. You use the class itself. You invoke them like this Classname.method(...);
Concept of OO is talks about controlling/accessing data from an object, but static methods need not to be called using an object and they belong to class rather than object.
--Cheers
© 2022 - 2024 — McMap. All rights reserved.