继承
源于抽象类的思想
抽象类包含了事物的共有属性和方法 ,为继承提供了一个出发点.
抽象类的作用就是让子类继承,去重新编写抽象类中的抽象方法(也为重写或覆写)
抽象类也为基类,
子类也称为派生类.他们之间的关系是一种 IS –A的关系
继承对程序员来说重点就是共同点,因为有共同点才能重写
定义抽象类使用abstsract关键字,定义的抽象方法就是为了在子类中重写该方法(override)
而继承的基类可以使抽象类 ,也可以不是抽象类.
所以在定义方法的时候注意:
- 如果是抽象类的抽象方法,那么就不用添加虚方法,原因就在于抽象类的方法默认是虚方法
- 而定义一般的类,期需要子类重写的方法就必须定义为虚方法,在方法前加关键字 virtual
所以说继承是运用了重写(覆写)的方法.
该方法的特点是:
(覆写)特点
- 只有虚方法或抽象方法才能实现
- 只有通过使用override关键字来实现
- 要求(三相同)
-
相同的方法名 -
相同的参数列表 - 相同的返回值类型
以上的要求是必须满足的,缺一不可,如果不满足,使用的时候就会出错.
下面看一个例子
定义基类Animal, 子类 cat 和dog Class Animal ///基类 { Public Virtual string shout() { Return ""; } } Class Cat:Animal //派生类 { Pulic Override string shout() { String result =””; For (int i=0; i<shoutNum;i++) Result+=”苗”; Return “我的名字”+ name +” “+ result’ } } Class Dog:Animal { Pulic Override string shout() { String result =””; For (int i=0; i<shoutNum;i++) Result+=”旺”; Return “我的名字”+ name +” “+ result’ } }
以上代码我们可以看到 ,这里是运用了重新编写基类方法而实现子类的.
我们还可以调用基类的构造方法,因为构造方法是子类不能继承的,只能是调用
说下,继承的特点:
- 第一,子类拥有父类非private属性和功能,
- 第二,子类具有自己的属性和功能,就是扩展父类没有的属性和方法,
- 第三是,子类还可以以自己的方法实现父类的功能(就是上面说的重写)
- 注意: 如果是基类的属性是protect,表示是子类对基类有完全的访问权限,但是其他类没有权限.
================================================================================================
回来, 对于基类的构造函数的调用 .子类可以运用Base关键字进行调用.比如我们封装一个方法,是获得调用函数的名
字.
如果我们不用继承的方法,那么就得在上面的两个类中分别写上
Protect string name=””;
Public cat(string name)
{ this.name=name;
}
代码重复性太多
但是如果调用了基类构造方法,在构造方法中写上以上代码, (将公共部分放在基类中).这样就避免了很多的重复性.
那么我们直接就可以改为以下代码
Class Dog:Animal
{
Public Cat():Base()
{
}
Public Cat(string name):base(name)
{
}
Pulic Override string shout()
{
String result =””;
For (int i=0; i<shoutNum;i++)
Result+=”旺”;
Return “我的名字”+ name +” “+ result’
}
}
我们还可以调用基类的构造方法将基类的一些函数放在构造函数中进行重新定义,当然这也是一种方法.思想是相同的
这样就可以避免重复的工作了.
然而继承也是有缺点的:
- 父类变,则子类不得不该.,会破坏包,增加类之间的耦合性
多态
- 多态是同一个操作作用于同一个对象,可以有不同的解释.产生不同的执行效果
- 多态通过派生类覆写基类中的虚函数方法类实现的
- 还可以通过重载类实现创建同名的多个方法的功能.
这就是多态的种类:
编译时的多态性 和运行时的多态性
编译时的多态:
编译时的多态是通过重载来实现的.是对于非虚的成员函数来说的.系统编译时.根据传递的参数.返回的类型等信息决定实现何种操作.
运行时的多态:
运行时的多态就是指直到系统运行时,才根据实际情况决定实现何种操作.运行时的多态是通过覆写(重写)虚函数实现的.
对于运行时的多态,这个方法在继承中已经体现.这里就不在累述了
下面主要讲解编译时的多态性
讲解: 是对于非虚的成员函数来说的.系统编译时.根据传递的参数.返回的类型等信息决定实现何种操作.
1
类中定义的方法的不同的版本.
如: public int circle(int x, int y)
Public double circle( double x, double y)
2 重载是提供了创建同名的多个方法的功能,但这些方法需要使用不同的参数类型.
注意:并不是只有构造函数才可重载,普通函数也可也重载
特点是: (两个必须一个可以)
方法名必须相同
参数列表必须不同
返回类型可以不相同;
下面就列举现在的机房收费系统进行说明
列举D层的对于卡类的操作
需要对卡分别进行如下操作
更新卡的信息(余额,使用状态)
更新卡的信息(修改卡号)
更新卡的结账状态
更新卡余额(添加到数据库)
那么就可以使用重载的方法,用同一个名称,不同的参数,就可以了
代码如下
'''<summary>
'''更新卡信息,将卡信息更新(按卡号更新充值卡使用状态,余额)
'''</summary>
'''<param name="state">使用状态</param>
'''<param name="balance">余额</param>
'''<param name="cardNumber">卡信息</param>
PublicFunction Update(ByVal
state AsString,ByVal
balanceAsSingle,ByVal
cardNumberAsLong)AsIntegerImplementsICardDao.Update
'''<summary>
'''修改卡信息,将卡号为cardNumber的卡的信息更新为card
'''</summary>
'''<param name="enCard">卡信息</param>
'''<param name="cardNumber">要更新的卡的卡号</param>
PublicFunction Update(ByVal
enCard AsCardEntity,ByVal
cardNumberAsLong)AsIntegerImplementsICardDao.Update
'''<summary>
'''根据卡号将已注册未结账的卡的结账状态更新为已结账
'''</summary>
'''<param name="cardNumber">卡号</param>
'''<param name="isCheckout">结账状态</param>
PublicFunction Update(ByVal
cardNumber AsLong,ByVal
isCheckoutAsString)AsIntegerImplementsICardDao.Update
'''<summary>
'''更新卡内余额(把卡余额信息更新到数据库),返回受影响行数
'''</summary>
'''<param name="balance">余额</param>
'''<param name="cardNumber">卡号</param>
PublicFunction Update(ByVal
balance AsSingle,ByVal
cardNumberAsLong)AsIntegerImplementsICardDao.Update
到这里基本的继承与多态就完结了,在谈一些基本的注意,就是 对于使用了继承或多台的类
他们保持了对上上层的封装性 . 上层调用方式时,只是能看到同样的方法名,看到 这个方法被重载多少次, 这就会封装的好处.示例图
下面用一幅图简单说下继承与多态的关系
关系图
多态与继承的关系图