问题
One interesting aspect of extension methods in .NET is the fact that you can apply them to interfaces. For me, it seems nice that I can define functionality near the interface without defining an abstract class that clutters the assembly.
I know that abstract classes are not obsolete or anything, but how do you feel about utilizing this side effect in your code?
Example:
public static class IUserExtensions
{
public static bool IsCurrentUser(this IUser user)
{
return (HttpContext.Current.User != null &&
HttpContext.Current.User.Identity.Name == user.ID.ToString());
}
}
public interface IUser {
int ID { get; set; }
}
回答1:
What extension methods lets you do is to focus in on what abstract classes should actually be doing. There's a temptation to implement "utility" code in abstract classes because it will be used by implementers even though it may not be part of the logical inheritance tree. Extension methods let you attach these utility methods to the interface without cluttering up your abstract base classes.
EDIT
Specifically, I would apply these guidelines.
Inheritance
- DO use inheritance if the behavior is part of the logical behavior of the base class
- DO NOT use inheritance if the behavior is cross-cutting (applies to things outside of your object hierarchy). These will require duplication.
Utility Classes
- DO use utility classes (static classes) if the behavior does not logically belong to the class it's acting on
- DO NOT use utility classes if they modify the internal state of the object it's acting on. State modification should be reserved only for the object implementation hierarchy.
Extension Methods
- DO use the same decision for extension methods as you would for utility classes when they create less friction. If adopting extension methods feels less natural, don't do it.
- DO use extension methods to add utility to classes you don't have control over (like string).
- DO NOT use extension methods when the behavior is consumed by the class it is extending. While it is possible to do it, it feels contrived
- DO NOT use extension methods just because you can. In fact don't deviate from good old fashioned OOP unless you have to. When you have to, however, extension methods are a relatively uesful and harmless decision to make.
EDIT 2
Thought of another DO for extension methods
DO use extension methods to provide a natural language (internal DSL) for certain implementations. Here's a silly example.
int age = getAge();
if (age.IsDraftAge() && !age.IsLegalDrinkingAge())
{
Console.WriteLine(@"You cannot drink until your birthdate on {0}.
Join the army instead.",
age.GetYearWhenGettingDrunkIsOk());
}
回答2:
I have used this functionality several times - and in fact, this functionality was created specifically for the purpose of decorating interfaces without modifying them, hence LINQ. All the goodness that is LINQ (to Objects at least) is based on extension methods to IEnumerable<T>.
However, I don't feel that extension methods in any way replace abstract base classes for when you need them. Extension methods cannot access the extended class's private state - extension methods look like instances, but are still static.
Extension methods and abstract base classes solve two different types of problems, and the choice to use either of these paradigms should not depend on each other.
My answer to your title question is thus: No, the existence of Extension Methods do not make Abstract Base Classes less attractive. If one believes that the existence of Extension Methods makes Abstract Base Classes less attractive, then one wasn't using Abstract Base Classes correctly in the first place.
回答3:
No, it will reduce some missuses of abstract classes.
An abstract class should contain default implementations/behaviors the subclasses can override. If factored appropriately, this means you could override just a single behavior of the class, and work with the defaults for the rest. Extension methods provide something really different to this.
回答4:
I do like extension methods because it has given me the ability to define Find(Predicate), Remove(Predicate) etc on IList<T>
which I have been missing. I do not think you can say they are a replacement for abstract classes.
I have also defined extension methods to add generic behavior. I love my ToJson extension method on object or ToXml quite handy.
The only problem I have with your example is I always look IsCurrentUser as a property not a method and alas we have no extension properties. But I'm nitpicking
They are completly unrelated. I use an abstract class when I want to model a behavior, that others will implement or inherit.
回答5:
No, abstract classes are not less attractive. Abstract classes provide the proper paradigm for object hierarchies.
Extension methods are only really useful if you need to add instance methods to an already existing class but can't modify the code directly.
回答6:
Extension methods are nice, but you can't compare them or their usage to abstract classes. Don't forget what encapsulation is, it's one of the pillar of OOP...
回答7:
I think it depends on your use-
If your main concern is refactoring to minimize the number of source files and/or classes in an assembly, then yes, extension methods are definitely the way to go, and abstract classes will probably end up being used less.
However, for those who care more about what abstract classes represent conceptually, not much has changed. It still makes sense in a code-organizational context to put "public int getCalories()" in abstract class "Food", as it'd be silly for the person eating it (the code using a subclass of food) to define how many calories it has.
回答8:
In a word: Yes. Due to the fact that abstract classes impose a lot on future implementations, general advice seems to be to create abstract classes that implement interfaces (e.g. DBDataReader : IDataReader). So long as a method does not require access to the internal state of an object, I see no reason not to render it as an extension method. You get the functionality without the cost.
回答9:
I think there are absolutely cases where this is a good idea. Linq is a great example of the benefits, but there is another: streams.
The whole reason streams are an abstract class is because they had to support methods like BeginRead, ReadByte, etc. Stream could be an interface, and all of those methods could be extension methods instead. This would make it possible to do things like inherit from a non-stream class and add stream functionality, and make it (more) natural to add potentially useful stream methods like 'dump stream contents to memory buffer'.
回答10:
If you don't need to access protected fields from the extension method, then it's AFAIK the way to go, since you can inherit multiple interfaces and get all the related extensions this way (while you can only derive from a single abstract class).
回答11:
I have not used anything past .NET 2.0, so I had no idea you could do that. Seems weird to me; interfaces are not for implementations. I would find that confusing. Also, the example that you show is a class, not an interface.
来源:https://stackoverflow.com/questions/651884/with-the-advent-of-extension-methods-are-abstract-classes-less-attractive