Disclaimer: I think the rules are almost the same in most OO languages, but since I'm most familiar with C# I'll be relating to this specific language.
I think that the use of attributes and reflection could be largely reduced if static members would apply the same principles as OO instances.
Static properties and methods can be "overridden" by decedents by using the new keyword, but they cannot be forced to implement one via an interface, neither can the 'base' keyword be used (only explicitly naming the base type is supported). To make things worse, the members cannot be referenced via an instance, but have to always be specifically qualified with the exact type.
Constructors also have limited "inheritance" support, one can choose which base constructor is called, but you cannot force an object to support a constructor that takes certain parameters by defining it in an interface.
The best hint I could find to answer this question so far is this one on stack overflow (answering a different question).
In his answer Jörg points out three principals that apply to Object Orientation:
- messaging,
- local retention and protection and hiding of state-process, and
- extreme late-binding of all things.
Now I fully understand that if you want to pass on a state-full class from one method to another as an object, these principles make sense. However in my opinion the principle of inheritance, overriding base methods with alternative or additional functionality, could also be beneficial to stateless business logic.
One example where forcing an object to implement a certain constructor would be helpful is with de-serialization. For example where the constructor should accept an XML node. In C# it is dynamically implementable using reflection, but having compile-time errors and avoiding the reflection boilerplate would add lots of value!
Static method/member interfaces would be helpful in situations where some aspects of a value are type specific, without any relation to the instance. For example a class could have a DisplayName, Unit, Weight, Factor or other aspects that are the same across all instances of the specific type, regardless of the instance value. Attributes (or Annotation) can be used to exploit these without the need to create an instance, however, there again it's extra boilerplate code and no way to enforce their implementation with compile-time errors.
I admit there are many simple ways to work around these points, I'm not looking for workarounds. Returning a static value in an instance-property is quite common, and it is not that much overhead to create an instance of an object just to read out the type-specific aspects, but I'd like to know the rationale background on why static things have been systematically excluded. I have heard about "the virtual stack" before, but don't really know how it works technically (and cannot find any simple explanation on the net).
Are the reasons of technical or philosophical nature?
Edit: elaborating on static interfaces:
An example of how I think a static interface could provide a strongly typed, compiletime checked, alternative to reflection:
public staticInterface MyStaticInterface
{
constructor(XmlNode node);
string DisplayName { get; }
int Weight { get; }
}
The usage:
public void FillNodesToolBox()
{
MyStaticInterface[] nodes =
assembly.GetTypes().Where(t => t.Implements<MyStaticInterface>());
for (int i = nodes.Length - 1; i >= 0 ; i--)
{
Console.WriteLine(string.Concat(
nodes[i].DisplayName, " (", nodes[i].Weight.ToString(), ")"));
}
}
Looking back, this actually looks like making my Type object inherit from System.Type, adding some properties to it, which is different than a static member...
string.Empty != typeof(string).Emty
(the latter will not compile).
Maybe I'm starting to find the answer, but it feels like I'm walking in a paradoxical circle, it doesn't quite 'snap' yet....
objects
which are singletons that otherwise behave like normal classes and allow inheritance, interfaces, etc. which is IMHO a much more object-oriented approach than static members.