【问题标题】:Is this a correct way to use polymorphism这是使用多态性的正确方法吗
【发布时间】:2013-10-03 22:13:41
【问题描述】:

我的系统中有几个类

//this was not made an Interface for some WCF reasons
public abstract class BaseTransmission
{
    protected internal abstract string Transmit();

    //other common properties go here
}

还有一些像

这样的子类
public class EmailTransmission : BaseTransmission
    {
        //This property is added separately by each child class
        public EmailMetadata Metadata { get; set; }

        protected internal override string Transmit()
        {
            //verify email address or throw
            if (!Metadata.VerifyMetadata())
            {
                throw new Exception();
            }
        }
    }

在其他地方,我创建了一个带有签名Transmit(BaseTransmission transmission) 的方法。我正在从我的代码的另一部分调用此方法,如下所示:

TransService svc = new TransService();
EmailTransmission emailTrans = new EmailTransmission(); // this inherits from BaseTransmission
svc.Transmit(emailTrans);

这解决了我的目的。但是通常当我看到多态的例子时,我总是看到引用类型是基类类型,它指向一个子类类型的实例。所以通常在多态的典型例子中

EmailTransmission emailTrans = new EmailTransmission();

通常是

BaseTransmission emailTrans = new EmailTransmission();

我不能这样做,因为EmailTransmission EmailMetadata 不同于FaxMetadata。因此,如果我将引用声明为 BaseTranmission 类型并将其指向 EmailTranmission 类型的实例,我将无法访问 EmailTransmission 的 EmailMetadata 属性。

我想知道我在上面所做的是否是对多态性的滥用,以及它是否以某种方式“破坏”了多态性。如果它滥用多态性,那么正确的做法是什么。

【问题讨论】:

  • 是的,我觉得不错。服务本身与基类一起工作,所以你应该没问题。
  • 之所以使用BaseTransmission 类型的变量是因为代码并不关心实际类型是什么。这通常是因为它只会调用 BaseTransmission 类型的方法。但是,由于您正在调用其中一个子类中的特定于类型的方法,因此您必须使用该类型的变量。这段代码没有任何问题。
  • 让我印象深刻的一件事是您的评论“此属性由每个子类单独添加”。所以听起来 BaseTransmission 的所有孩子都将有一个 Metadata 属性。我想知道在理想情况下,您是否会有元数据的接口或基类,并在 BaseTransmission 中公开访问器。不过,它完全没问题,绝对没有任何问题。
  • 为什么没有类 Metadata 作为 EmailMetadata 和 FaxMetadata 的基础?
  • @AlessandroD'Andria 我有一个所有 Metadata 类都实现的 IMetadata 接口,但它们之间的共同点是一个名为 VerifyMetadata() 的方法。除此之外,电子邮件的元数据与传真的元数据完全不同。所以它们都有不同的属性,每个子类都添加了这些属性。鉴于此,您认为在这种情况下可以做什么?

标签: c# .net oop polymorphism


【解决方案1】:

您正在做的事情是绝对正确的,应该可以正常工作。将子类传递给采用基类的函数/方法应该不是问题。

但是,关于您的示例:

这解决了我的目的。但是通常当我看到多态的例子时,我总是看到引用类型是基类类型,它指向一个子类类型的实例。所以通常在多态的典型例子中

EmailTransmission emailTrans = new EmailTransmission();

通常是

BaseTransmission emailTrans = new EmailTransmission();

如果BaseTransmission 是一个接口或抽象类,然后您需要构造一个特定版本的BaseTransmission,就会这样做。有时,如果您不需要额外的组件,有些人也喜欢使用它来保持他们的代码干净。最常见的用法是泛型,例如当您想创建List,但需要实现特定版本的操作系统List,例如ArrayListLinkedList

【讨论】:

    【解决方案2】:

    通常您更喜欢使用基本类型

    BaseTransmission emailTrans = new EmailTransmission();
    

    这可以让你的抽象保持干净,并帮助你不要重复自己。这在以下场景中很有用:假设用户可以选择如何联系她/他(电子邮件、传真、文本)。当你需要发送一些东西时,你只需要一个single 方法,它接受BaseTransmission 对象和参数,比如BaseParameter

    注意:如果看起来,好像没有多少代码可以共享,可以定义一个接口ITransmitter,用它来表示一个类可以发送一些东西,比如:

    ITransmitter transmitter = new EmailTransmission();
    

    【讨论】:

      【解决方案3】:

      这是完全有效的。多态模式用于TransService 服务Transmit 方法。 它适用于一个或多个类中可以是morphed 的类。

      您使用基类或派生类声明变量的事实取决于您并取决于您的具体情况。

      【讨论】:

        【解决方案4】:

        嗯,这是完全有效的情况:当您使用基类类型时,就像在 TransService.Trasmit 方法。

        看起来唯一奇怪的是:

        protected internal abstract string Transmit();
        

        真的需要protectedinternal吗? 如果是,请跳过这个概念。

        【讨论】:

          【解决方案5】:

          那应该完全没问题。在传输方法中,对象被称为 BaseTransmission,因此“向下转换”不太明显。 (事先有这个评论,但这应该是一个答案)

          【讨论】:

            猜你喜欢
            • 2012-05-11
            • 2018-12-31
            • 2021-04-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-01-05
            相关资源
            最近更新 更多