1

I've been looking into empty interfaces and abstract classes and from what I have read, they are generally bad practice. I intend to use them as the foundation for a small search application that I am writing. I would write the initial search provider and others would be allowed to create their own providers as well. My code's intent is enforce relationships between the classes for anyone who would like to implement them.

Can someone chime in and describe if and why this is still a bad practice and what, if any alternatives are available.

namespace Api.SearchProviders
{
    public abstract class ListingSeachResult
    {
        public abstract string GetResultsAsJSON();
    }

     public abstract class SearchParameters
     {
     }

     public interface IListingSearchProvider
     {
         ListingSeachResult SearchListings(SearchParameters p);
     } 
  }
4

1 回答 1

1

空类和接口通常仅作为通用约束“有用”;这些类型本身不能使用,并且泛型约束通常是人们可以将它们与其他有用的东西结合使用的唯一上下文。例如,如果IMagicThing封装了一些值,一些实现是可变的,而另一些则不是,想要记录与 an 关联的值的方法IMagicThing可能会这样写:

void RecordValues<T>(T it) where T:IImagicThing,IIsImmutable {...}

whereIIsImmutable是一个空接口,其契约规定任何实现它并为任何属性报告某些值的类必须永远为该属性报告相同的值。按照指示编写的方法可以知道其参数在合同上必须表现为IMagicThing.

从概念上讲,如果一个接口的各种实现会对它们的行为做出不同的承诺,那么能够将这些承诺与约束结合起来似乎很有帮助。不幸的是,这种方法有一个相当讨厌的限制:除非知道满足所有约束的特定类型以及从哪个对象派生,否则不可能将对象传递给上述方法。如果只有一个约束,则可以将对象强制转换为该类型,但如果有两个或更多,这将不起作用。

由于上述使用约束泛型时的困难,最好通过定义一个派生自但不添加新成员IMagicThing的接口来表达“承诺是不可变的”的概念。一个期望 an 的方法不会接受任何不实现不可变接口的方法,即使它碰巧是不可变的,但是如果一个对碰巧实现的 an 的引用,则可以将该引用转换为后一种类型并且将它传递给需要它的例程。IImmutableMagicThingIMagicThingIImmutableMagicThingIMagicThingIMagicThingIImmutableMagicThing

顺便说一句,对于空类类型,我还可以看到另一种用法:作为身份令牌。一个类不需要有任何成员来充当字典键、监视器锁或弱引用的目标。特别是如果有与这种用法相关联的扩展方法,那么为此目的定义一个空类可能比使用Object.

于 2013-09-26T17:55:18.750 回答