First off, I totally understand that an interface cannot contain a static method because what would the method act on - that is clear. Suppose I want an interface to mandate a method that is particular to a class but acts statically (and as an interface method may be shared by many classes.)

To propose a crazy example: let's say I have various cookers (Pressure Cooker, Wok, Microwave, Oil Fryer, Grill, Air Fryer and so on...) and I want them all to implement a Cook method to which I will pass ingredients so the method itself could be static and thus does not use any of the properties of the class. If I actually make this method static then there is no contract that I can use to constrain all these Cookers. If I create an interface with an instance method called Cook then I wonder how I could call it.

Does it make sense to create this interface? How do I call this method when I do not have an instance? Could I create a static instance of each implementing class (like Wok.Default or Wok.Empty) and use it to call the method when I only have ingredients and no instance? In this method I could decide whether I have a valid instance and either act on that instance or use passed ingredients.

Is this crazy? Is there a better way? Is there a pattern that applies to this? I've considered various patterns like Proxy, Facade, Adapter, and Decorator but nothing seems to exactly fit. The Mediator also seems close because I suspect it would be useful to have a 'intercept' in between that could identify the class thru a parameter but I am trying to not couple the method to an 'intercept' unless absolutely necessary. I am open to suggestion.

有帮助吗?

解决方案

Many have said

Static methods do not have access to instance data. They can’t access non static fields that are part of an objects state.

This is absolutely true but is causes many people to make this assumption:

Methods that don’t use non static fields should be static.

This is not true because it ignores that there is another reason a method should be non-static: non-static methods can be dynamically dispatched. That is, they can be polymorphic.

Thus, a method that doesn’t use non static instance data can still have a good reason to be non-static.

This means that this code:

PressureCooker.Cook()

and this code:

new PressureCooker().Cook();

can accomplish exactly the same thing. However, supporting the second one allows this to work as well:

cooker.Cook();

The difference with this third one is that it doesn’t know that cooker is a PressureCooker. That’s decided elsewhere.

Now cooker can have a type that must have a Cook method but what kind of implementation (Wok, Microwave, Oil Fryer, Grill, Air Fryer) is also decided elsewhere.

So this lets you enforce an interface just fine. The type system ensures that whatever kind of cooker you’re given it will have a cook method.

As a bonus, you don’t even have to know if the method uses non static fields. That was also decided elsewhere.

In fact, since nothing is being passed to Cook() and nothing is being returned the only thing being decided here is do it now.

It’s very powerful to be able push details away and focus on just one thing. It makes your code robust because there are few things that impact it when they change. This lets those other things be dealt with elsewhere.

许可以下: CC-BY-SA归因
scroll top