C# 中的多态性 先来看一个例子:
代码语言:javascript复制class A { }
class B : A { }
public class Program
{
public static void Main(string[] args)
{
A a = new B(); //No error?!
}
}
为什么没有抛出错误?当B继承A时,它就变成了A的一种形式,这意味着它可以在需要时作为A传递。
再来看:
代码语言:javascript复制using System;
public class Program
{
public static void Main(string[] args)
{
DoSomething(new A());
DoSomething(new B());
}
static void DoSomething(A obj)
{
Console.WriteLine($"Object Type: {obj.GetType()}");
}
}
打印:
代码语言:javascript复制Object Type: A
Object Type: B
其它例子:
代码语言:javascript复制using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
List<A> objs = new List<A>();
objs.Add(new A());
objs.Add(new B());
foreach (A obj in objs)
{
Console.WriteLine($"Object Type: {obj.GetType()}");
}
}
}
打印:
代码语言:javascript复制Object Type: A
Object Type: B
不同于Java。Java中的泛型实现,是采用运行时类型擦除实现的,所以打印List集合看不到具体类型
重写方法
多态性的另一个用法:重写方法。
现在可以使用两个关键字来完成方法重写:virtual和override。Virtual本质上是方法/字段以类的形式被重写。Override是对方法/字段的调用
来看看实际应用:
代码语言:javascript复制using System;
public class Program
{
public static void Main(string[] args)
{
DoStuff(new A());
DoStuff(new B());
}
static void DoStuff(A obj)
{
obj.DoSomething();
}
}
class A
{
public virtual void DoSomething()
{
Console.WriteLine("I did something in A's method!");
}
}
class B : A
{
public override void DoSomething()
{
Console.WriteLine("I did something in B's method!");
}
}
打印:
代码语言:javascript复制I did something in A's method!
I did something in B's method!
这两个对象都作为类型A传递,但对同一方法有不同的实现!
sealed关键字
代码语言:javascript复制class A
{
public virtual void DoSomething()
{
Console.WriteLine("I did something in A's method!");
}
}
class B : A
{
public sealed override void DoSomething()
{
Console.WriteLine("I did something in B's method!");
}
}
class C : B
{
public override void DoSomething()
{
Console.WriteLine("I did something in C's method!");
}
}
打印:
代码语言:javascript复制error CS0239: 'C.DoSomething()': cannot override inherited member 'B.DoSomething()'
我们可以看到,sealed切断了重写方法的调用链
注意:当使用一个类的形式作为基类时,任何new的方法/字段将无法隐藏原来的方法/字段。
示例:
代码语言:javascript复制using System;
public class Program
{
public static void Main(string[] args)
{
DoStuff(new A());
DoStuff(new B());
}
static void DoStuff(A obj)
{
obj.DoSomething();
}
}
class A
{
public void DoSomething()
{
Console.WriteLine("I did something in A's method!");
}
}
class B : A
{
public new void DoSomething()
{
Console.WriteLine("I did something in B's method!");
}
}
打印:
代码语言:javascript复制I did something in A's method!
I did something in A's method!
由于将B作为类型a传递,new关键字失败(这就是为什么存在override !) new 的一个例子:
代码语言:javascript复制using System;
public class Program
{
public static void Main(string[] args)
{
new A().DoSomething();
new B().DoSomething();
}
}
class A
{
public void DoSomething()
{
Console.WriteLine("I did something in A's method!");
}
}
class B : A
{
public new void DoSomething()
{
Console.WriteLine("I did something in B's method!");
}
}
打印:
代码语言:javascript复制I did something in A's method!
I did something in B's method!
关键字base
最后一个关键字是base。base关键字允许从它的形式上访问基类方法和字段,而不必创建一个全新的对象。
示例:
代码语言:javascript复制using System;
public class Program
{
public static void Main(string[] args)
{
new B().DoSomething();
}
}
class A
{
public virtual void DoSomething()
{
Console.WriteLine("I did something in A's method!");
}
}
class B : A
{
public override void DoSomething()
{
Console.WriteLine("I did something in B's method!");
base.DoSomething();
}
}
打印:
代码语言:javascript复制I did something in B's method!
I did something in A's method!