c#的多态(使用到的关键字说明)

个人理解:  

用不同的派生类或接口来实现来实现基类的方法,从而达到不同的效果。在实现多态时有可能用到如下关键字。
一、new
1)可以不完全替换基类(或叫做隐藏基类)的方法、属性、字段。如果将派生类的实例强制转换为基类的实例,就仍然可以调用隐藏类的成员。(感觉New关键字在这里的用处不大,即使替换了还可以访问)

二、virtual override
1)可以完全替换基类(或叫做隐藏基类)的方法、属性。此关键字只能作用于方法、属性、事件、索引器,不能作用于字段。可以使派生类的实例完全替换来自基类的成员,即使将派生类的实例强制转换为基类的实例,仍旧访问的是派生类的成员。
2)可以多层完全替换, 无论在派生类和最初声明虚成员的类之间已声明了多少个类,虚成员都将永远为虚成员。如果类 A 声明了一个虚拟成员,类 B 从 A 派生,类 C 从类 B 派生,则类 C 继承该虚拟成员,并且可以选择重写它,而不管类 B 是否为该成员声明了重写。这时如果强制转化类C实例为类A,调用对应的虚方法,实质仍是调用类C实例的虚方法,即使类D继承类C并隐藏类C的虚方法,这时使用类型为A、C访问D的实例,调用相应的虚方法,实质仍是调用类C实例的虚方法。
3)停止替换(密封方法),派生类可以通过将重写声明为密封的来停止虚拟继承。这需要在类成员声明中将 sealed 关键字放在 override 关键字的前面。
4)替换密封方法, 替换派生类可以通过使用 new 关键字替换密封的方法。(感觉这个是New关键字的最大用处,可以替换密封方法)
3、base
1)已替换或重写某个方法或属性的派生类仍然可以使用此关键字访问该类基类的该方法或属性。

 

参考文章:
通过继承,一个类可以用作多种类型:可以用作它自己的类型、任何基类型,或者在实现接口时用作任何接口类型。这称为多态性。C# 中的每种类型都是多态的。类型可用作它们自己的类型或用作 Object 实例,因为任何类型都自动将 Object 当作基类型。
多态性不仅对派生类很重要,对基类也很重要。任何情况下,使用基类实际上都可能是在使用已强制转换为基类类型的派生类对象。基类的设计者可以预测到其基类中可能会在派生类中发生更改的方面。例如,表示汽车的基类可能包含这样的行为:当考虑的汽车为小型货车或敞篷汽车时,这些行为将会改变。基类可以将这些类成员标记为虚成员,从而允许表示敞篷汽车和小型货车的派生类重写该行为。
当派生类从基类继承时,它会获得基类的所有方法、字段、属性和事件。若要更改基类的数据和行为,您有两种选择:可以使用新的派生成员替换基成员,或者可以重写虚拟的基成员。
使用新的派生成员替换基类的成员需要使用 new 关键字。如果基类定义了一个方法、字段或属性,则 new 关键字用于在派生类中创建该方法、字段或属性的新定义。new 关键字放置在要替换的类成员的返回类型之前。例如:
public class BaseClass
{
    public void DoWork() { }
    public int WorkField;
    public int WorkProperty
    {
        get { return 0; }
    }
}
public class DerivedClass : BaseClass
{
    public new void DoWork() { }
    public new int WorkField;
    public new int WorkProperty
    {
        get { return 0; }
    }
}

使用 new 关键字时,调用的是新的类成员而不是已被替换的基类成员。这些基类成员称为隐藏成员。如果将派生类的实例强制转换为基类的实例,就仍然可以调用隐藏类成员。例如:
DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork();  // Calls the old method.

为了使派生类的实例完全接替来自基类的类成员,基类必须将该成员声明为虚拟的。这是通过在该成员的返回类型之前添加 virtual 关键字来实现的。然后,派生类可以选择使用 override 关键字而不是 new,将基类实现替换为它自己的实现。例如:
public class BaseClass
{
    public virtual void DoWork() { }
    public virtual int WorkProperty
    {
        get { return 0; }
    }
}
public class DerivedClass : BaseClass
{
    public override void DoWork() { }
    public override int WorkProperty
    {
        get { return 0; }
    }
}

字段不能是虚拟的,只有方法、属性、事件和索引器才可以是虚拟的。当派生类重写某个虚拟成员时,即使该派生类的实例被当作基类的实例访问,也会调用该成员。例如:
DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork();  // Also calls the new method.

可以使用虚方法和属性预先计划未来的扩展。因为在调用虚成员时不考虑调用方正在使用的类型,所以派生类可以选择更改基类的外在行为。
无论在派生类和最初声明虚成员的类之间已声明了多少个类,虚成员都将永远为虚成员。如果类 A 声明了一个虚拟成员,类 B 从 A 派生,类 C 从类 B 派生,则类 C 继承该虚拟成员,并且可以选择重写它,而不管类 B 是否为该成员声明了重写。例如:
public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}
public class C : B
{
    public override void DoWork() { }
}

派生类可以通过将重写声明为密封的来停止虚拟继承。这需要在类成员声明中将 sealed 关键字放在 override 关键字的前面。例如:
public class C : B
{
    public sealed override void DoWork() { }
}

在上面的示例中,方法 DoWork 对从 C 派生的任何类都不再是虚方法,但它仍是 C 的实例的虚方法 -- 即使将这些实例强制转换为类型 B 或类型 A 也是如此。派生类可以通过使用 new 关键字替换密封的方法,如下面的示例所示:
public class D : C
{
    public new void DoWork() { }
}

在此情况下,如果在 D 中使用类型为 D 的变量调用 DoWork,被调用的将是新的 DoWork。如果使用类型为 C、B 或 A 的变量访问 D 的实例,对 DoWork 的调用将遵循虚拟继承的规则,即把这些调用传送到类 C 的 DoWork 实现。
已替换或重写某个方法或属性的派生类仍然可以使用基关键字访问基类的该方法或属性。例如:
public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}
public class C : B
{
    public override void DoWork()
    {
        // Call DoWork on B to get B's behavior:
        base.DoWork();
        // DoWork behavior specific to C goes here:
        // ...
    }
}
[说明] 说明:
建议虚拟成员在它们自己的实现中使用 base 来调用该成员的基类实现。允许基类行为发生使得派生类能够集中精力实现特定于派生类的行为。未调用基类实现时,由派生类负责使它们的行为与基类的行为兼容。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值