3-10 抽象
面向对象 抽象
抽象方法和抽象属性,必须卸载抽象类类。
抽象类不能算是一个完整的类,因为抽象类类的抽象属性和抽象方法,都没有具体的实现代码。
抽象不能被实例化,只可以作为其他类的父类进行使用。
class Program
{
static void Main()
{
var w = new M16();
w.Area = "2km";
w.OpenFire();
((Weapon)w).OpenFire();
}
}
class M16 : Weapon
{
public override string Area {
get;
set;
}
public override void OpenFire()
{
Console.WriteLine("开火,火力范围" + Area);
Console.ReadKey();
}
}
abstract class Weapon
{
public abstract void OpenFire();
public abstract string Area
{
get;
set;
}
}
所有的抽象方法和抽象属性,只能写在抽象类类。
能否实例化 | 能否继承 | 方法和属性有没有代码主体 | 重写方式 | |
---|---|---|---|---|
virtual | 所在的类可以实例化 | 所在类可以被继承 | √ | 根据需要使用override重写 |
abstract | 无法实例化 | 可以继承 | × | 强制要求继承抽象类的子类必须重写所有抽象内容 |
面向对象 接口
类只能继承一个父类(包括抽象类),但是他可以继承多个接口。
接口是功能的抽象定义。
比如我们有猫、车、杯子三种完全无关类型。我们定义一个武器接口后,可以为这三个类都加上武器接口。
加上武器接口后,这三个类就都有了开火的功能。并且我们可以把他们都存在一个列表中,以武器接口类型去进行调用,从而用for以武器接口类型调用开火。这样的好处是我们可以把关注点移到功能上,而不再考虑数据类型到底是什么。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace Test4
{
class Program
{
static void Main()
{
var car = new Car();
var cat = new Cat();
var cup = new Cup();
List<IWeapon> list = new List<IWeapon>();
list.Add(car);
list.Add(cat);
list.Add(cup);
foreach (IWeapon item in list)
{
item.OpenFire();
}
Console.ReadKey();
}
}
public class Cup : IWeapon,IDie
{
public string WeaponName { get; set; }
public void GoToDie()
{
Console.WriteLine("杯子碎了");
}
public void OpenFire()
{
Console.WriteLine("投掷攻击");
}
}
public class Cat : Animal, IWeapon
{
public string WeaponName { get; set; }
public void OpenFire()
{
Console.WriteLine("猫猫爪击");
}
}
public class Car : Carrier, IWeapon
{
public string WeaponName { get; set; }
public void OpenFire()
{
Console.WriteLine("汽车人变形");
}
}
/// <summary>
/// 武器接口
/// </summary>
public interface IWeapon
{
string WeaponName { get; set; }
void OpenFire();
}
/// <summary>
/// 死亡接口
/// </summary>
public interface IDie
{
void GoToDie();
}
public class Carrier
{
public void Run() {
Console.WriteLine("开动");
}
}
public class Animal
{
public virtual void Talk()
{
Console.WriteLine("打招呼");
}
}
}
<table>
<tr><th></th><th>接口</th><th>抽象类</th><tr>
<tr><td>关键词</td><td>Interface</td><td>abstract</td></tr>
<tr><td>子类继承</td><td>一个子类可以继承多个接口</td><td>一个子类只能继承一个父类</td></tr>
<tr><td>子类的实现</td><td>不要override,直接写就行</td><td>通过override重写</td></tr>
<tr><td>方法的定义</td><td colspan="2">只要定义,不需要具体代码块,具体代码实现在子类中进行</td></tr>
<tr><td>属性的定义</td><td colspan="2">自定义属性的get/set访问器的存在,访问器的具体代码在子类中实现</td></tr>
<tr><td>实例化</td><td colspan="2">不能实例化</td></tr>
</table>
练习
抽象类 Carrier 载具,他有抽象方法Run,正常属性Name载具名。
逃生系统接口 IEscape , 有一个Escape方法;
武器系统 IWeapon,有OpenFire方法和Reload方法。
建立三个载具的子类,Car,Boat,Plane,继承载具。
建立若干个具体的类(具体车船飞机型号),继承自Car、Boat和Plane,根据实际情况,为这些类选择性的继承武器和逃生接口。
建立Carrier列表,以及IEscape和IWeapon的两个列表,把建立的实例丢到列表中。
对于载具列表,显示"XXX起航"/"XXX起飞"/"XXX启动",武器调用Reload和OpenFire,逃生设备,调用Escape;