What's the Correct Alternative to Static Method Inheritance

What's the correct alternative to static method inheritance?

One idea:

public abstract class Fruit<T>
where T : Fruit<T>, new()
{
public static T CreateInstance()
{
T newFruit = new T();
newFruit.Initialize(); // Calls Apple.Initialize
return newFruit;
}

protected abstract void Initialize();
}

public class Apple : Fruit<Apple>
{
protected override void Initialize() { ... }
}

And call like so:

Apple myAppleVar = Fruit<Apple>.CreateInstance();

No extra factory classes needed.

C# Inheriting Static Methods?

A work-around might be to declare a property of type Action in the base abstract class, that holds the method to be called. Then initialize this property during derived classes instantiation, by calling base class constructor:

abstract class DoSomething
{
public Action DoWhateverItIsThatIDo { get; set; }

protected DoSomething() { DoWhateverItIsThatIDo = DoSomething.DoIt; }

protected DoSomething(Action whatAction)
{
DoWhateverItIsThatIDo = whatAction;
}

protected static void DoIt()
{
Console.WriteLine("You asked the abstract class to work. Too bad.");
}
}

class InspireMe : DoSomething
{
public InspireMe() : base(InspireMe.DoIt) { }

private static void DoIt()
{
Console.WriteLine("You are amazing.");
}
}

class InsultMe : DoSomething
{
public InsultMe() : base(InsultMe.DoIt) { }

private static void DoIt()
{
Console.WriteLine("You aren't worth it.");
}
}

class DoWhatBaseClassDoes : DoSomething
{
public DoWhatBaseClassDoes() : base() {}
}

class Program
{
static void Main(string[] args)
{
DoSomething worker = new InsultMe();
worker.DoWhateverItIsThatIDo();

worker = new InspireMe();
worker.DoWhateverItIsThatIDo();

// In this case base class method is invoked
worker = new DoWhatBaseClassDoes();
worker.DoWhateverItIsThatIDo();
}
}

Is there an alternative way of implementing inheritance of static methods in Dart?

I would probably go with an extension on a List:

extension RandomElement<T> on List<T> {
T random() => this[Random().nextInt(length)];
}

And then you can use it like this:

SkinColors.values.random();
ShortHair.values.random();

Alternatives to static methods in Java

Albeit, I totally agree in the point of "Static is the wrong thing to be using here", I kind of understand what you're trying to address here. Still instance behavior should be the way to work, but if you insist this is what I would do:

Starting from your comment "I need to create an instance of it just to get a string that is really static in behaviour"

It is not completely correct. If you look well, you are not changing the behavior of your base class, just changing the parameter for a method. In other words you're changing the data, not the algorithm.

Inheritance is more useful when a new subclass wants to change the way a method works, if you just need to change the "data" the class uses to work probably an approach like this would do the trick.

class ModelBase {
// Initialize the queries
private static Map<String,String> selectMap = new HashMap<String,String>(); static {
selectMap.put( "Album", "select field_1, field_2 from album");
selectMap.put( "Artist", "select field_1, field_2 from artist");
selectMap.put( "Track", "select field_1, field_2 from track");
}

// Finds all the objects for the specified class...
// Note: it is better to use "List" rather than "ArrayList" I'll explain this later.
public static List findAll(Class classToFind ) {
String sql = getSelectSQL( classToFind );
results = execute( sql );
//etc...
return ....
}

// Return the correct select sql..
private static String getSelectSQL( Class classToFind ){
String statement = tableMap.get( classToFind.getSimpleName() );
if( statement == null ) {
throw new IllegalArgumentException("Class " +
classToFind.getSimpleName + " is not mapped");
}
return statement;

}
}

That is, map all the statements with a Map. The "obvious" next step to this is to load the map from an external resource, such as a properties file, or a xml or even ( why not ) a database table, for extra flexibility.

This way you can keep your class clients ( and your self ) happy, because you don't needed "creating an instance" to do the work.

// Client usage:

...
List albums = ModelBase.findAll( Album.class );

...

Another approach is to create the instances from behind, and keep your client interface intact while using instance methods, the methods are marked as "protected" to avoid having external invocation. In a similar fashion of the previous sample you can also do this

// Second option, instance used under the hood.
class ModelBase {
// Initialize the queries
private static Map<String,ModelBase> daoMap = new HashMap<String,ModelBase>(); static {
selectMap.put( "Album", new AlbumModel() );
selectMap.put( "Artist", new ArtistModel());
selectMap.put( "Track", new TrackModel());
}

// Finds all the objects for the specified class...
// Note: it is better to use "List" rather than "ArrayList" I'll explain this later.
public static List findAll(Class classToFind ) {
String sql = getSelectSQL( classToFind );
results = execute( sql );
//etc...
return ....
}

// Return the correct select sql..
private static String getSelectSQL( Class classToFind ){
ModelBase dao = tableMap.get( classToFind.getSimpleName() );
if( statement == null ) {
throw new IllegalArgumentException("Class " +
classToFind.getSimpleName + " is not mapped");
}
return dao.selectSql();
}
// Instance class to be overrided...
// this is "protected" ...
protected abstract String selectSql();
}
class AlbumModel extends ModelBase {
public String selectSql(){
return "select ... from album";
}
}
class ArtistModel extends ModelBase {
public String selectSql(){
return "select ... from artist";
}
}
class TrackModel extends ModelBase {
public String selectSql(){
return "select ... from track";
}
}

And you don't need to change the client code, and still have the power of polymorphism.

// Client usage:

...
List albums = ModelBase.findAll( Album.class ); // Does not know , behind the scenes you use instances.

...

I hope this helps.

A final note on using List vs. ArrayList. It is always better to program to the interface than to the implementation, this way you make your code more flexible. You can use another List implementation that is faster, or does something else, without changing your client code.

C# virtual (or abstract) static methods

No, you cannot override a static method. "static" also means that it is statically bound by the compiler, so the actual method to be called is not found at runtime, but bound at compile time.

What you should do is make the class non-static. Make the method virtual and override it and make full benefit of real inheritance. Then, if you really need it, make a static entry point to a reference of your class. For instance a static factory, singleton (it's an anti-pattern in most of the cases but is as good as a static class) or just a static property.

C# static member inheritance - why does this exist at all?

So, the "inheritance" of static
members merely looks like namespace
pollution

That's right, except that one guy's pollution is another guy's added spicy flavouring.

I think Martin Fowler, in his work on DSLs, has suggested using inheritance in this way to allow convenient access to static methods, allowing those methods to be used without class name qualification. So the calling code has to be in a class that inherits the class in which the methods are defined. (I think it's a rotten idea.)

In my opinion, static members should not be mixed into a class with a non-static purpose, and the issue you raise here is part of the reason why it's important not to mix them.

Hiding private static mutable data inside the implementation of an otherwise "instancey" class is particularly horrible. But then there are static methods, which are even worse mixers. Here's a typical use of static methods mixed into a class:

public class Thing
{
// typical per-instance stuff
int _member1;
protected virtual void Foo() { ... }
public void Bar() { ... }

// factory method
public static Thing Make()
{
return new Thing();
}
}

It's the static factory method pattern. It's pointless most of the time, but even worse is that now we have this:

public class AnotherThing : Thing { }

This now has a static Make method which returns a Thing, not a AnotherThing.

This kind of mismatch strongly implies that anything with static methods should be sealed. Static members fail to integrate well with inheritance. It makes no sense to have them heritable. So I keep static things in separate static classes, and I gripe about redundantly having to declare every member static when I've already said that the class is static.

But it's just one of those too-late-now things. All real, working languages (and libraries, and products) have a few of them. C# has remarkably few.



Related Topics



Leave a reply



Submit