在多态继承层次中执行类型安全的最佳做法 [英] Best practice for enforcing type safety in polymorphic inheritance hierarchies

查看:184
本文介绍了在多态继承层次中执行类型安全的最佳做法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎遇到了这样的情况,还没有找到一个可以接受的解决方案。

I seem to run into this situation quite a lot and have yet to find a solution that I find acceptable.

我经常会有并行继承层次结构一个层次结构中的方法作为参数从其他层次结构中传递匹配的类。

Quite often I will have parallel inheritance hierarchies where a method in one hierarchy gets passed the matching class from the other hierarchy as a parameter.

这是一个可能更好的解释这个例子。

Here is an example that probably explains this better.

abstract class Animal
{
    public virtual void Eat(Food f)
    {
    }
}

abstract class Food
{
}

class LionFood : Food
{
}

class ElephantFood : Food
{
}

class Lion : Animal
{
    public override void Eat(Food f)
    {
        // It is only ever valid to pass LionFood here as the parameter.
        // passing any other type of Food is invalid and should be prevented
        // or at least throw an exception if it does happen.
    }
}

在过去,我通常做了基类通用以允许实现具体的类定义类型如下。

In the past, I have usually made the base class generic to allow the implementing concrete class to define the type as follows..

abstract class Animal<T> where T : Food
{
    public abstract void Eat(T f);
}

class Lion : Animal<LionFood>
{
    public override void Eat(LionFood f)
    {
    }
}

起初,这似乎是一个非常好的解决方案,因为它提供了编译时类型的安全性。但是我使用的越多,我越开始认为以这种方式使用泛型是一个反模式的。问题是Animal基类不能以多态方式使用。例如,您不能轻易地编写一个将处理任何类型的动物的方法,而不管其实际具体类型如何。

At first this seems like a very good solution because it provides compile-time type safety. But the more I use it, the more I am starting to think that using generics in this way is infact an anti-pattern. The problem is that the Animal base class cannot be used in a polymorphic way. You cannot, for example, easily write a method that will process any type of Animal regardless of its actual concrete type.

每当我使用这种泛型解决方案时,我总是似乎最终得到协同和逆变界面,只是为了尝试并提供我想要的多态性行为。这很快就会失控,一些功能是不可能的,因为无法提供正确的界面。

Every time I use this generics solution, I always seem to end up with covariant and contravariant interfaces all over the place just to try and provide the polymorphic behaviour I want. This gets out of hand pretty quickly and some functionality is not possible simply because the correct interface cannot be provided.

当然另一个选择是不使用泛型并执行运行时类型检查Eat方法,如下所示:

Of course another option is to not use generics and perform runtime type checking in the Eat method like this:

    public override void Eat(Food f)
    {
        if (f.GetType() != typeof(LionFood))
        {
            throw new Exception();
        }
    }

这比我想象的更好,但我不是一个巨大的粉丝,只是因为缺乏编译时类型的安全。

This is better than nothing I suppose but I'm not a huge fan of it simply because of the lack of compile-time type safety.

所以这一切..我的问题是..最好的做法是什么提供多态性行为,同时确保一些类型的安全?

So after all that.. My question is.. What is the best practice to provide polymorphic behaviour while at the same time ensuring some type safety?

是否有一些OO设计技巧或模式,我错过了,将允许我避免并行继承层次结构在一起?

Is there some OO design trick or pattern that I am missing that will allow me to avoid the parallel inheritance hierarchies all together?

我很欣赏,这个问题有点主观,但有贡献的每个人都有分数,我会选择最佳答案作为答案。

I appreciate that this question is somewhat subjective, but there are points available for everyone who contributes and I'll choose the best response as the answer.

感谢您的查找。

编辑:

考虑到这一点,我意识到我的例子并不真实。当然,不可能以多态方式使用Animal,因为传递给Eat的类型将始终取决于Animal的实际底层类型(多态调用的启动器将不知道)!我需要考虑一个更好的例子,说明我的实际情况。

Having thought about this I realise that my example given doesn't really make sense. Of course it is not possible to use Animal in a polymorphic way because the type passed to Eat will always depend on the actual underlying type of Animal (which the initiator of a polymorphic call will not know)! I need to think of a better example that illustrates my actual situation.

推荐答案

我认为常识和域名的要求规定正确的方法。使用这个例子,我会这样做

I think common sense and the requirements of the domain will dictate the proper approach. Working with this example, I'd do like this

 public class Lion:Animal
 {
       public override void Eat(Food f)
        {
           Eat(f as LionFood);
         }
       public void Eat(LionFood food)
        {
         //check for null food  
         //actually consume it
       }
  }

修改

我认为在这种情况下使用泛型是不适合的,因为如果一个动物可以玩玩具,玩具等等。你可以使用一些方法来实现一个抽象,每次有一个使用polymorhpism的参数的方法时,使用泛型是尴尬的。

I think using generics is not suited in this case, because what if an Animal can play with a Toy, hunt a specific Animal and so on. You can have a number of methods with arugments that implement an abstraction, it's awkward to use generics every time there is a method with an argument that uses polymorhpism.

这篇关于在多态继承层次中执行类型安全的最佳做法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆