Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does having static members make a language less object-orientated?

Tags:

java

scala

I'm learning Scala at the moment and I came across this statement in Odersky's Programming Scala 2nd edition:

one way in which Scala is more object-orientated than Java is that classes in Scala cannot have static members.

I'm not sufficiently experienced in either Java or Scala to understand that comparison. Why does having static members make a language less OO?

like image 642
M.K. Avatar asked Apr 06 '14 04:04

M.K.


3 Answers

Odersky's statement is valid and significant, but some people don't understand what he meant.

Let's say that in Java you have a class Foo with method f:

class Foo {
  int f() { /* does something great */ }
}

You can write a method that takes a Foo and invokes f on it:

void g(Foo foo) { foo.f(); }

Perhaps there is a class SubFoo that extends Foo; g works on that too. There can be a whole set of classes, related by inheritance or by an interface, which share the fact that they can be used with g.

Now let's make that f method static:

class Foo {
  static int f() { /* does something great */ }
}

Can we use this new Foo with g, perhaps like so?

g(Foo);  // No, this is nonsense.

Darn. OK, let's change the signature of g so that we can pass Foo to it and have it invoke f.

Ooops -- we can't. We can't pass around a reference to Foo because Foo is not an instance of some class. Some people commenting here are confused by the fact that there is a Class object corresponding to Foo, but as Sotirios tried to explain, that Class object does not have an f method and Foo is not an instance of that class. Foo is not an instance of anything; it is not an object at all. The Class object for Foo is an instance of class Class that has information about Foo (think of it as Foo's internal Wikipedia page), and is completely irrelevant to the discussion. The Wikipedia page for "tiger" is not a tiger.

In Java, "primitives" like 3 and 'x' are not objects. They are objects in Scala. For performance your program will use JVM primitives for 3 and 'x' wherever possible during execution, but at the level you code in they really are objects. The fact that they are not objects in Java has rather unfortunate consequences for anyone trying to write code that handles all data types -- you have to have special logic and additional methods to cover primitives. If you've ever seen or written that kind of code, you know that it's awful. Odersky's statement is not "purism"; far from it.

In Scala there is no piece of runtime data that is not an object, and there is no thing you can invoke methods on that is not an object. In Java neither of these statements in true; Java is a partially object-oriented language. In Java there are things which are not objects and there are methods which aren't on objects.

Newcomers to Scala often think of object Foo as some weird replacement for Java statics, but that's something you need to get past quickly. Instead think of Java's static methods as a non-OO wart and Scala's object Foo { ... } as something along these lines:

class SomeHiddenClass { ... }
val Foo = new SomeHiddenClass  // the only instance of it

Here Foo is a value, not a type, and it really is an object. It can be passed to a method. It can extend some other class. For example:

abstract class AbFoo { def f:Int }
object Foo extends AbFoo { def f = 2 }

Now, finally, you can say

g(Foo)

It is true that a "companion object" for a class is a good place to put non-instance methods and data for the class. But that companion object is an object, so the usual rules and capabilities apply.

The fact that in Java you put such methods on non-objects -- limiting how they can be used -- is a liability, not a feature. It is certainly not OO.

like image 149
AmigoNico Avatar answered Sep 20 '22 00:09

AmigoNico


I am not sure I completely buy that argument, but here is one possible reasoning.

To an object-oriented purist, everything should be an object, and all state should be encapsulated by objects. Any static member of a class is by definition state which exists outside of an object, because you can use it and manipulate it without instantiating an object. Thus, the lack of static class members makes for a more pure object-oriented language.

like image 31
merlin2011 Avatar answered Sep 22 '22 00:09

merlin2011


Well, with static members like methods you don't have any objects to create and nevertheless you can call such static methods. You only need the static classname in order to set the namespace for these methods, for example:

long timeNow = System.currentTimeMillis(); // no object creation

This rather gives a feeling like in procedural languages.

like image 23
Meno Hochschild Avatar answered Sep 20 '22 00:09

Meno Hochschild