周广明的博客

.Net & MS SQL Tech
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C#类的三大特性之继承

Posted on 2008-08-29 19:54  Zhougm  阅读(3446)  评论(2)    收藏  举报
     对象的继承代表了一种'Is-a'的关系,如果两个对象A和B,可以描述为'B是A',则表明B可以继承A.如猫是动物,说明猫和动物之间是继承与被继承的关系.继承者还可以理解为是对被继承者的特殊化,因为它除了具备被继承者的特性外,还具备自己独有的个性.如,猫可能拥有抓老鼠,爬树等其他动物不具有的属性.因而,在继承关系中,继承者可以完全替换被继承者,反之则不成立.     如果子类继承于父类,第一,子类拥有父类非Private的属性和功能.第二,子类具有自己的属性和方法,即子类可以扩展父类没有的属性和功能.第三,子类还可以以自己的方式实现父类的功能(方法重写).
     另外,在C#中子类从它的父类中继承的成员有方法,域,属性,事件,索引指示器.但对于构造方法和析构函数(有一些特殊的除外),它不能被继承,只能被调用.对于调用父类的成员,可以用base关键字.
     我们下面还是看下具体实例吧.在下面的代码中我穿插了事件委托,方法重载,方法覆写等一些知识点.闲话不多说了,我们看代码吧.

    
//sealed class Animal //使用sealed将实现对类的封装,结果就是这个类无法被继承,密封类不能同时又是抽象类
    public class Animal
    
{
        
protected string _name = ""//注意修饰符这里用的是protected
        protected int _eye ;
        
protected int _leg ;

        
//定义一个事件,了解下事件委托的实现
        public delegate void SoundPlayHander(string name,int shoutnum); //定义一个委托
        public event SoundPlayHander SoundPlay; //定义一个事件

        
//构造方法
        public Animal()
        
{
            _name
="无名";
            _eye
=2;
            _leg
=4;
        }


        
public Animal(string name,int eye,int leg)
        
{
            _name
=name;
            _eye
=eye;
            _leg
=leg;
        }


        
protected int shoutNum=1//注意修饰符这里用的是protected
        public int ShoutNum //用存取器创建属性,这样可以引用private的字段,提高安全性.
        {
            
get 
            
{
                
return shoutNum;
            }

            
set
            
{
                shoutNum
=value;
                
if (SoundPlay != null//如果有事件注册的话就调用相应事件
                {
                    SoundPlay(_name,value); 
// 调用所有注册对象的方法
                }

            }

        }


        
public string Leg(int leg) //为父类创建一个方法
        {
            
switch (leg)
            
{
                
case 0:
                    
return _name+",没有腿怎么走路呢?";
                    
break;
                
case 2:
                    
return _name+",2条腿,很普遍嘛.";
                    
break;
                
case 4:
                    
return _name+",4条腿跑起来还不快啊!";
                    
break;
                
default:
                    
return _name+",看来不正常哦!";
                    
break;
            }

        }


    }


    
public class Cat:Animal //创建一个继承类
    {
        
private int _age;
        
private string _color;

        
public Cat():base() //子类构造方法需要调用父类同样参数类型的构造方法,用basa关键字代表父类.
        {

        }


        
public Cat(string name, int age, string color, int eye, int leg):base(name, eye, leg) //用:base完成了子类在初始化时与父类的通信.
        {
            _age
=age;
            _color
=color;
        }


        
public string Leg(string name, int leg) //为子类写一个简单的方法,它与基类中的方法是同名的,但签名不同.
        {
            
return "我的名字叫" + name + ",有" + Convert.ToString(leg) + "条腿 !";
        }


        
//public string Leg(int leg) //这个方法与基类中的方法和签名都完全一样,这样就隐藏了基类的同名方法.假设我们是有意
        public new string Leg(int leg) //假设我们是有意隐藏的,所以使用new关键字显式隐藏从基类继承的同名方法
        {
            
string result=base.Leg(leg);
            
return "父类方法被覆写,我们调用基类同名方法所得结果为:" + result;
        }


        
public string Trait() //子类特有的方法
        {
            
string result = "";
            
for (int i = 0; i < shoutNum; i++)
            
{
                result 
+= "喵,";
            }

            
return result+"我的名字叫" + _name + ",年龄为" + _age + "岁,体色是" + _color + "." ;
        }

    }


    
//创建事件发生时所需要做的方法
    public void cat_SoundPlay(string name, int shoutnum)
    
{
        
string result = "";
        
for (int i = 0; i < shoutnum; i++)
        
{
            result 
+= "喵,";
        }

        Response.Write(result
+name+"来了,Jerry快逃 !<br>");
    }


    
protected void Page_Load(object sender, EventArgs e)
    
{

        
if (!IsPostBack)
        
{
            Cat cat 
= new Cat("Tom"1"While"24);
            cat.SoundPlay 
+= new Animal.SoundPlayHander(cat_SoundPlay);//用 '+=' 注册事件,注销事件用 '-='
            cat.ShoutNum = 3;//改变值触发事件
            Response.Write(cat.Trait() + "<br>");
            Response.Write(cat.Leg(
"Tom",4+ "<br>");
            Response.Write(cat.Leg(
4+ "<br>");
        }

     }

 

 运行结果

      

      总结一下, 继承的优点是:继承使得所有子类公共的部分都放在了父类,使得代码得到了共享,这就避免了重复.另外,继承可以使得修改或扩展继承而来的实现都较为容易.但不能因为继承有这么好的优点,在有代码重复时,我们就要多多在程序里使用,这样是不好的,如有一个'猫'类和一个'狗'类,程序代码差不多,但我们不可能用狗类来继承猫类吧,要不然就真会狗逮耗子,多管闲事了.哈哈,当然也可能啦.转到正题,我们一定要区分使用继承时的具体情况,因为继承会破坏封装,父类实现细节暴露给子类,这其实是增加了两个类之间的耦合性.继承显然是一种类与类之间强的耦合的关系,不符合我们的设计模式. 
     那么在什么情况下使用继承呢?我们记住开头所说的一句话:当两类之间具备'Is-a'的关系时,就可以考虑用继承了. 
     关于类的继承就写这么多吧,希望给朋友们有所帮助.