c# 继承 和 关键字:abstract,const,override,readonly,static,virtual,base,this
最近手头紧,老想去银行弄点钱,哈哈,弄个银行业务来做个小例子,边做例子,边总结业务。
1.定义存钱和取钱接口。接口命名,一般在名字前面加一个大写的I,表示接口。
注意这里,我们把namespace定义成:CSharp.Bank,也就是说在这个namespace下,都是关于银行的东西。便于我们归类而已。没其它用处。
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
namespace CSharp.Bank
{
interface IBank
{
bool SaveMoney(decimal money);
bool GetMoney(decimal money);
}
}
2. 写一个抽象(abstract)类。(完整代码,包含上面的interface)
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
namespace CSharp.Bank
{
interface IBank
{
bool SaveMoney(decimal money);
bool GetMoney(decimal money);
}
public abstract class CenterBank : IBank
{
//银行剩余存款,自己给自己多弄点。
private decimal _total = 9999999; //好多钱啊,不愁啦。
#region IBank 成员
public bool SaveMoney(decimal money)
{
//throw new NotImplementedException();
//存钱
this._total += money; // 等于this._total = this._total + money;
return true; //存钱成功啦
}
public bool GetMoney(decimal money)
{
//throw new NotImplementedException();
//先判断存款是否够我取的,我们不能透支啊,经济危机来了,要节约哦。
if (this._total >= money)
{
this._total -= money;
return true; //取钱成功
}
else
{
return false;//取钱失败,因为余额不足。
}
}
//定义一个抽象方法
public abstract decimal GetTotal();
#endregion
}
}
抽象类不能直接被实例化,用abstract来声明,如:public abstract class CenterBank
CenterBank : IBank 表示CenterBank 继承(或者说“实现”)自IBank, 用的操作是一个冒号":".其它语言,如java/php,用的是extend,比如:CenterBank extend IBank.
在c#中,一个类,可以同时继承(或叫“实现”)多个接口,比如:CenterBank :IBank,IBank2,IBank3,IBank4 , 多个接口之间用逗号隔开。
this._total += money; -- this关键字,表示当前类的对象。
类简单理解,比如:class AA{},那么AA就是一个类,那么什么是对象呢?比如:
AA objAA1 = new AA();
AA objAA2 = new AA();
那么objAA1,objAA2就是类AA的对象,或者叫:实例。
public abstract decimal GetTotal(); 定义抽象方法,抽象方法同接口的方法,不过是用abstract关键来声明而已,抽象方法不包含具体的实现代码。
3.具体的类。(可以拿来用的那种)
在这里,我们为抽象类:CenterBank 增加了一个属性:Total
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
namespace CSharp.Bank
{
interface IBank
{
bool SaveMoney(decimal money);
bool GetMoney(decimal money);
}
public abstract class CenterBank : IBank
{
//银行剩余存款,自己给自己多弄点。
private decimal _total = 9999999; //好多钱啊,不愁啦。
//定义一个属性。类似方法
public decimal Total
{
set { _total = value; }
get { return _total; }
}
#region IBank 成员
public bool SaveMoney(decimal money)
{
//throw new NotImplementedException();
//存钱
this._total += money; // 等于this._total = this._total + money;
return true; //存钱成功啦
}
public bool GetMoney(decimal money)
{
//throw new NotImplementedException();
//先判断存款是否够我取的,我们不能透支啊,经济危机来了,要节约哦。
if (this._total >= money)
{
this._total -= money;
return true; //取钱成功
}
else
{
return false;//取钱失败,因为余额不足。
}
}
//定义一个抽象方法
public abstract decimal GetTotal();
#endregion
}
//中国银行
public class ChinaBank : CenterBank
{
public override decimal GetTotal()
{
//throw new NotImplementedException();
return base.Total; //返回我实际的余额
}
}
public class CCB : CenterBank
{
public override decimal GetTotal()
{
//throw new NotImplementedException();
return 0; //建行比较烂,就返回一个0给我。
}
}
}
当 ChinaBank继承自 CenterBank后,就必须要实现抽象方法:GetTotal(),实现方式:
public override decimal GetTotal()
override 关键字就是表示重载父类的方法。
return base.Total; //返回我实际的余额
base 关键字就是调用父类的方法,也就是说base是父类的对象,是对父类的引用。
4.有了银行,我们就要开始花钱啦。
给抽象类,增加了一个虚方法:AutoAddMoney(),新增两个类:Shop和Me
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
namespace CSharp.Bank
{
interface IBank
{
bool SaveMoney(decimal money);
decimal GetMoney(decimal money);
}
public abstract class CenterBank : IBank
{
//银行剩余存款,自己给自己多弄点。
private decimal _total = 0; //
//定义一个属性。类似方法
public decimal Total
{
set { _total = value; }
get { return _total; }
}
#region IBank 成员
public bool SaveMoney(decimal money)
{
//throw new NotImplementedException();
//存钱
this._total += money; // 等于this._total = this._total + money;
return true; //存钱成功啦
}
public decimal GetMoney(decimal money)
{
//throw new NotImplementedException();
//先判断存款是否够我取的,我们不能透支啊,经济危机来了,要节约哦。
if (this._total >= money)
{
return money;
}
else
{
return 0;//取钱失败,因为余额不足。
}
}
//定义一个抽象方法
public abstract decimal GetTotal();
public virtual void AutoAddMoney()
{
this._total += 500;
}
#endregion
}
//中国银行
public class ChinaBank : CenterBank
{
public override decimal GetTotal()
{
//throw new NotImplementedException();
return base.Total; //返回我实际的余额
}
//public override void AutoAddMoney()
//{
// base.AutoAddMoney();
//}
}
public class CCB : CenterBank
{
public override decimal GetTotal()
{
//throw new NotImplementedException();
return 0; //建行比较烂,就返回一个0给我。
}
}
//定义一个商店,卖卖车,卖卖房子.
public class Shop
{
//定义车,一辆车15万
public const decimal Car = 150000;
//定义房子,一套房子50万
public const decimal House = 500000;
}
public class Me
{
//定义一个变量,用来存放手里的现金
private static decimal _money = 0;
//定义两个变量,表示是否有房有车,默认为false,表示没车没房。
private bool _hasCar = false;
private bool _hasHouse = false;
public void Buy()
{
BuyCar();
BuyHouse();
Console.WriteLine("有车啦?");
Console.WriteLine(_hasCar ? "有":"没有");
Console.WriteLine("有房啦?");
Console.WriteLine(_hasHouse ? "有" : "没有");
Console.WriteLine("还剩几毛?");
Console.WriteLine(GetBalance());
if (GetBalance() > 300000)
{
Console.WriteLine("Oh,yeah,我好有钱啊");
}
else
{
Console.WriteLine("穷啊");
}
Console.ReadLine();
}
public static void SetMoney(decimal money)
{
Me._money = money;
}
//买车
private bool BuyCar()
{
if (Me._money >= Shop.Car)
{
_hasCar = true; //修改_hasCar的值为true,表示我们有车啦
Me._money -= Shop.Car; // 买了车后,我的现金就少啦。
return true;
//如果_money >= _car ,方法执行到这里就退出了。表示购买成功。
}
//如果_money < _car ,就返回false。表示购买不成功。
return false;
}
//买房
private bool BuyHouse()
{
if (Me._money >= Shop.House)
{
_hasHouse = true;
Me._money -= Shop.House;
return true;
}
return false;
}
//获取余额
private decimal GetBalance()
{
return Me._money;
}
}
}
虚方法定义方式:
public virtual void AutoAddMoney()
使用virtual关键字。其实virtrual 方法跟普通方法没啥区别。但是官方的解释是virtrual的行为类似abstract方法,不过virtrual方法有自己的代码实现,而abstract方法没有自己的实现。
所以,我觉得还不如拿virtrual方法直接和普通方法比较,比如和上面的private decimal GetBalance()比较。在用法上,这两个没啥区别,一样用。
const和readonly。 总体来讲,这两个关键字都是限制字段只能读,不能写。唯一的区别就是定义const字段时,必须在声明的时候,就要赋值,如上面的例子。
而readonly字段可以在声明的时候或者构造函数的时候赋值。
static关键字 -- 上面的现金余额使用的static关键字来定义。因为我们的现金只有一个实例。没有多个实例。 看下面运行结果解释。
运行测试代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CSharp.Bank;
namespace CSharp
{
class Program
{
static void Main(string[] args)
{
//实例化ChinaBank类。 使用new关键字。
ChinaBank objChinaBank = new ChinaBank();
//调用方法
objChinaBank.SaveMoney(1000000);
Console.WriteLine(objChinaBank.GetTotal());
objChinaBank.AutoAddMoney();
Console.WriteLine(objChinaBank.GetTotal());
Me.SetMoney(objChinaBank.GetMoney(999999));
Me objMe1 = new Me();
objMe1.Buy();
Me objMe2 = new Me();
objMe2.Buy();
}
}
}
运行结果:
在测试代码里面,我们定义了两个Me类的实例:
Me objMe1 = new Me();
objMe1.Buy();
Me objMe2 = new Me();
objMe2.Buy();
为了是现金保持同一个实例,所以我们比如使用static字段来定义_money.
第一次运行之前,我们的取的现金是999999
第一次运行的时候,剩余金额是349999,
第二次运行的时候,初始金额就是349999了,而不是999999。可以去掉_money的static属性,然后重新测试代码。
最后,关键字详细解释:http://msdn.microsoft.com/zh-cn/library/x53a06bb(VS.80).aspx