Overriding static members: Nonsense?

Am I really the only one to be tempted to sometimes write absurd thigs like this?!

abstract class MyAbstractClass
{
	public static abstract string MyString	{ get; }
}

Of course it is absurd. At least in .Net/Mono, Java, and I guess most if not all compiled OO languages.

For those who would consider the code above legal: A static member is attached to the class where it is defined. Overriding it does not make any sense.

Actually, you need in any case to explicitly tell which class the member belongs to in order to be able to call it.

class Class1
{
	public static void MyMethod()
	{	Console.WriteLine("I am Class1.MyMethod");	}
}
 
class Class2:Class1{ }
 
class Class3:Class2
{
	public static new void MyMethod()
	{	Console.WriteLine("I am Class3.MyMethod");	}
}
 
class Main
{
	public static void Main(string[] args)
	{
		Class1.MyMethod();	// prints "I am Class1.MyMethod"
		Class2.MyMethod();	// prints "I am Class1.MyMethod"
		Class3.MyMethod();	// prints "I am Class3.MyMethod"
 
	}
}

The term “static” was not made randomly. It was chosen to tell there cannot be any confusion for the compiler in choosing the proper definition to use for the member.
Contrarily, the definition to use for dynamic members depends on the context and usually can be evaluated during runtime only.

For instance:

class Class1
{
	public void MyMethod()
	{	Console.WriteLine("I am Class1.MyMethod");	}
}
 
class Class2:Class1{ }
 
class Class3:Class2
{
	public new void MyMethod()
	{	Console.WriteLine("I am Class3.MyMethod");	}
}
 
class Main
{
	public static void Main(string[] args)
	{
		this.Test(new Class1());
		this.Test(new Class2());
		this.Test(new Class3());
	}
 
	public void Test(Class1 obj)
	{	obj.MyMethod();	}
 
}

Le method obj.MyMethod(); will depend on the type of obj.
The compiler cannot know which method will be called and the link will be made during runtime.

So, if the code at the beginning of this post is so absurd, why try to write it?

It seems to me that it is mostly because static can handle two definitions, between which there can be some kind of friction.
- On one hand, the concept of being attached to the class by opposition to the instance.
- On the other hand, the disambiguation of types for the compiler.

The first one is mostly conceptual:
_ Insects have 6 legs
_ This ant is moving a leaf

As all insects have 6 legs, it can look logical to define this value at class level, using a static member.

class Insect
{
	public static int NbLegs
	{
		get:{ return 6; }
	}
}

After all, defining a value for the instance would conceptually imply that the value could change from one instance to another, no?

Now, let’s imagine we want to create an interface to define all animals for which we know the number of legs per family.

interface AnimalsWeKnowTheNumberOfLegs{...}

The fact that the number of legs will be known for all instances that will implement this interface must be stated.

interface AnimalsWeKnowTheNumberOfLegs
{..
	int NbLegs{	get;	}
..}

But, if we find more logical that the value is attached to the class rather than to its instances?

interface AnimalsWeKnowTheNumberOfLegs
{..
	static int NbLegs{	get;	}
..}

File=AnimalsWeKnowTheNumberOfLegs.cs, Line=10, Column=24, Type=Error, Priority=Normal, Description=The modifier `static’ is not valid for this item(CS0106)

ARghle…

But… Wait a moment.
What are we trying to express there?

We would like to express that the number of legs of all instances of the classes that implement AnimalsWeKnowTheNumberOfLegs is a value that is defined for their class.
It is a bit tricky, I know…

By translating this proposal in using a static member, we are making a mistake:

A class property != A property shared amongst all instances of the class!!

The insect class does not have 6 legs! The insect class has no leg at all! It is a class, not an animal for god’ sake!
Only insects have 6 legs.

Yes, but then how do we express that the property is shared amongs all instances of the class?

- Wel, in .Net/Mono, we have the const keyword.

But we still do not have any way to force a child class to define a const.
In other words, it is not allowed to specify a const inside an interface, as an abstract member or even as virtual.

- In Java, you cannot. To my knowledge, final is the equivalent of readonly and not of const.

- In prototype-based languages, you just have to set the property on the prototype.
Ex en Javascript:

var o = {
};
 
var F = function(){};
F.prototype = o;
another_o = new F(); // o and another_o share the same prototype
 
o.prototype['my_shared_value'] = 25;
 
alert(o.my_share_value);
alert(another_o.my_shared_value);

- PHP also offers a const keyword. But the variables defined that way must be called like static members.

<?php
class MyClass
{
	const MyConstant = 'A constant';
}
 
echo MyClass::MyConstant;
$a = new MyClass();
echo $a->MyConstant;	// ERROR!
?>

Note that PHP also allows to write “static abstract function test()”.

No doubt my original temptation is coming from there.

- In python and other python-like languages, the situation is again a little confusing. The self keyword is used to call indifferently static or not members.
The following Boo code is perfectly valid:

class MyClass():
	_string = "A string"
 
	public def constructor():
		self.StaticMethod()
		Console.WriteLine(self._string)
 
	public static def StaticMethod():
		pass

As a conclusion, I do not see any real solution to enforce in an interface or an abstract class a property for which the value would be shared amongst all the instances of the class.
Of course, we can still code but the programmer is responsible for ensuring the immutability of a value for one class.

To my point of view, class-based OO languages do miss a level of abstraction to define this.
And this level of abstraction is exactly what the prototype concept in prototype-based language handles.

Is there a chance I ever can write things like this?:

class Insect(Animal):
	prototype:
		public NbLegs = 6;
 
	public def constructor():
		pass
  1. No comments yet.

  1. No trackbacks yet.