C#编程简短总结

封装

field一般为private,定义的时候可以不赋值不赋值的时候一般被构造函数初始化赋值,其值用来保存类实例的数据,可以被内部方法使用作为计算的数据来源。当需要继承类继承本类的时候,field要改为protected类型,这样继承类时子类可以对基类的field有完全访问权。

property一般为public,是向外暴露的窗口,属性可以为其他外部类使用

方法可以是public的,用来向外暴露,外部可以直接调用。

继承

如果子类继承于父类,第一:子类拥有父类非private的属性和功能;第二:子类具有自己的属性和功能,即子类可以扩展父类没有的属性和功能;第三:子类还可以以自己的方式实现父类的功能(方法重写)。

 

基类的构造函数不可以被子类继承,只能被子类调用,调用父类的成员时可以用base关键字。注子类的构造方法需要调用父类同样参数类型的构造方法,用base关键字代表父类。注意先要set filed为protected

如果基类有两个构造函数:

public Animal () {};

public Animal (sring name) {}

子类构造函数的写法:

public Cat (): base() {}

public Cat () : base(name) {}

具体例子如下:

Animal.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApplication1
{
    class Animal
    {
        protected string _name = "";
        protected int _barkTime = 3;
        public int BarkTime 
        {
            get { return _barkTime; }
            set { _barkTime = value; }
        }
        public Animal()
        {
            this._name = "无名氏";
        }
        public Animal(string name)
        {
            _name = name;
        }
    }
}
View Code
Cat.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApplication1
{
    class Cat : Animal
    {
        public Cat() : base() { }
        public Cat(string name) : base(name) { }


        public string Bark()
        {
            string result = "";
            for (int i = 0; i < BarkTime; i++)
            {
                result += " 喵! ";
            }
            return "我的名字叫" + _name + result;
        }
    }
}
View Code
Dog.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApplication1
{
    class Dog :Animal
    {
        public Dog() : base() { }
        public Dog(string name) : base(name) { }
        public string Bark() 
        {
            string result = "";
            for (int i = 0; i < BarkTime; i++)
            {
                result += " 汪! ";
            }
            return "我的名字叫" + _name + result;
        }

    }
}
View Code
MainClass

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Cat myCat = new Cat("TuTu");
            var feedback = myCat.Bark();
            MessageBox.Show(feedback);

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Dog myDog = new Dog("旺财");
            myDog.BarkTime = 8;
            var feedback = myDog.Bark();
            MessageBox.Show(feedback);
        }
    }
}
View Code

 

多态和虚方法

第一:子类以父类的身份出现;第二:子类工作时以自己的方式来实现;第三:子类以父类的身份出现时,子类特有的属性和方法不可以使用。

为了使子类的实力完全接替来自父类的成员,父类必须将该成员声明为虚拟的(interface也是一种形式的虚拟)。这是通过在该成员的返回类型之前添加virtual关键字来实现。通常虚拟的是方法(虚方法还是可以有自己的方法体,实际做点事情),但除了字段不能虚拟,属性;事件;索引器都是可以虚拟的。子类可以选择override关键字,将父类的实现替换为自己的实现,这就是重写。

重构

上面的例子还是有一个部分比较冗余,就是每个动物都有一个Bark()方法,我们可以把这个方法提到基类去做。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApplication1
{
    class Animal
    {
        protected string _name = "";
        protected int _barkTime = 3;
        public int BarkTime 
        {
            get { return _barkTime; }
            set { _barkTime = value; }
        }
        public Animal()
        {
            this._name = "无名氏";
        }
        public Animal(string name)
        {
            _name = name;
        }
        
        public string Bark()
        {
            string result = "";
            for (int i = 0; i < BarkTime; i++)
            {
                result += GetBarkSound() + ",";
            }
            return "我的名字叫" + _name + result;
        }
        public virtual string GetBarkSound()
        {
            return "";
        }
    }
}
View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApplication1
{
    class Cat : Animal
    {
        public Cat() : base() { }
        public Cat(string name) : base(name) { }


        public override string GetBarkSound()
        {
            return "";
        }
    }
}
View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApplication1
{
    class Dog :Animal
    {
        public Dog() : base() { }
        public Dog(string name) : base(name) { }
        public override string GetBarkSound()
        {
            return "";
        }

    }
}
View Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private Animal[] _arrayAnimal;

        private void button1_Click(object sender, EventArgs e)
        {
            _arrayAnimal = new Animal[5];
            _arrayAnimal[0] = new Cat("小花");
            _arrayAnimal[1] = new Cat("阿毛");
            _arrayAnimal[2] = new Dog("兔子");
            _arrayAnimal[3] = new Cat("娇娇");
            _arrayAnimal[4] = new Dog("汪汪");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            foreach (Animal item in _arrayAnimal)
            {
                MessageBox.Show(item.Bark());
            }
        }
    }
}
View Code

 

抽象类和抽象方法

在类前面加上abstract,方法public后加上abstract。抽象类提供一个继承的出发点,当设计一个新的抽象类时,一定是用来做继承之用。所以在一个以继承关系形成的等级结构里面,树叶节点应该是具体类。

注意:第一:抽象类的抽象方法不能写任何具体实现;第二:抽象方法是必须被子类重写的方法;第三:如果类中包含抽象方法,那么类就必须定义为抽象类,无论是否包含其他一般方法。

所以如果我们一开始就把Animal类设成抽象类,根本就没有必要存在虚方法的父类。

只是改下Animal.cs为:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApplication1
{
    abstract class Animal
    {
        protected string _name = "";
        protected int _barkTime = 3;
        public int BarkTime 
        {
            get { return _barkTime; }
            set { _barkTime = value; }
        }
        public Animal()
        {
            this._name = "无名氏";
        }
        public Animal(string name)
        {
            _name = name;
        }
        
        public string Bark()
        {
            string result = "";
            for (int i = 0; i < BarkTime; i++)
            {
                result += GetBarkSound() + ",";
            }
            return "我的名字叫" + _name + result;
        }
        public abstract string GetBarkSound();  //注意这里一定不要写具体实现
    }
}
View Code

 接口

 接口内置有对属性和方法的简单声明(一样不可以声明任何成员的具体执行体),接口不能有构造函数和字段,不可以有修饰符,不能声明虚拟或者静态的。声明接口在语法上与声明抽象类完全相同。实现接口的类必须要实现接口的所有方法和属性。一个类可以支持多个接口,多个类也可以支持相同的接口。注意接口的命名在前面加一个大写的I。

同样是飞,鸟用翅膀飞,飞机用引擎飞,超人举起双手飞。若要把他们放在一起的话,用一个飞行行为的接口IFly来实现。

与抽象类的区别:

形态上:第一:抽象类可以给出一些成员的实现,接口不可以。第二:抽象类的抽象成员可以被子类部分实现,接口的成员需要实现类完全实现这些属性和方法。第三:一个类只能继承一个抽象类,但是可以实现多个接口。

继承关系上看:第一:类是对对象的抽象,所以抽象类是对对象的抽象(Animal),而接口是对行为的抽象(IFly)。

如果行为跨越不同类的对象用接口,对于一些相似类的对象用继承抽象类的方法。小猫,小狗,都是动物抽象类的子类,而飞机,麻雀,超人是完全不同种类的东西,用接口描述其共同能飞的特质。

一个类我们可以让其即继承一个基类同时又继承多个接口。

第三:抽象类是自底而上抽象出来的(从小猫小狗抽象到Animal类), 而接口则是自顶向下设计出来的(动物大会组织委员,并不知道谁来参加比赛,我只是预先设定了若干比赛项目,人来了根据自己的情况来选择参加的比赛)。

委托&事件

委托是对函数的封装,可以当作给要trigger的方法指定一个名称。而事件则是委托的一种特殊形式,当发生有意义的事件时,时间对象处理通知过程。委托是一种引用方法的类型,一旦委托分配了方法,委托将与该方法具有完全相同的行为,类和对象通过时间通知它们。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Cat
    {
        private string _name;
        public Cat(string name)
        {
            _name = name;
        }
        public delegate void CatShotEventHandler(); //声明CatShotEventHandler委托
        public event CatShotEventHandler CatShout;  //声明事件CatShout,后面没有(),它的类型是委托CatShotEventHandler
        public void Shout() //表明执行Shout()方法时,如果CatShout事件有新的委托登记方法,则按照注册顺序执行事件
        {
            Console.WriteLine("喵,我是{0}", _name);
            if (CatShout != null)   
            {
                CatShout(); //表示执行注册过的委托方法
            }
        }
    }
    class Mouse
    {
        private string _name;
        public Mouse(string name)
        {
            _name = name;
        }
        public void Run()
        {
            Console.WriteLine("老猫来了,{0}快跑", _name);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Mouse mouse1 = new Mouse("Jerry");
            Mouse mouse2 = new Mouse("Jack");
            Cat cat = new Cat("Tom");
            cat.CatShout += new Cat.CatShotEventHandler(mouse1.Run);    //为事件登记一个新的委托方法
            cat.CatShout += new Cat.CatShotEventHandler(mouse2.Run);    //为事件登记另一个新的委托方法
            cat.Shout();
            Console.ReadLine();
        }
    }
}
View Code

这里new Cat.CatShotEventHandler(mouse1.Run);的含义实际就是实例化一个委托,而委托的实例其实就是Mouse的Run方法。+=表示增加一个需要触发事件时通知的对象。-=就是减少一个需要触发事件时通知的对象。

那么如何传递事件对象到委托方法里呢?用EventArgs

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    public class CatShoutEventArgs : EventArgs
    {
        private string _name;
        public string Name  //用一个public的property,表示CatShout事件触发时需要传递Cat对象的名字
        {
            get { return _name; }
            set { _name = value; }
        }
    }
    class Cat
    {
        private string _name;
        public Cat(string name)
        {
            _name = name;
        }
        //声明委托CatShotEventHandler,此时委托所代表的方法不再是空的参数,而是有两个参数
        public delegate void CatShotEventHandler(object sender, CatShoutEventArgs args); 
        public event CatShotEventHandler CatShout;  
        public void Shout() 
        {
            Console.WriteLine("喵,我是{0}", _name);
            if (CatShout != null)   
            {
                CatShoutEventArgs e = new CatShoutEventArgs() { Name = _name};
               
                //因为CatShout是委托CatShotEventHandler的类型,
                //委托又是方法的注册,所以执行的时候要写两个参数
                CatShout(this, e);  
            }
        }
    }

    class Mouse
    {
        private string _name;
        public Mouse(string name)
        {
            _name = name;
        }
        public void Run(object sender, CatShoutEventArgs args)
        {
            Console.WriteLine("老猫{0}来了,{1}快跑", args.Name, _name);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Mouse mouse1 = new Mouse("Jerry");
            Mouse mouse2 = new Mouse("Jack");
            Cat cat = new Cat("Tom");
            cat.CatShout += new Cat.CatShotEventHandler(mouse1.Run);    //为事件登记一个新的委托方法
            cat.CatShout += new Cat.CatShotEventHandler(mouse2.Run);    //为事件登记另一个新的委托方法
            cat.Shout();
            Console.ReadLine();
        }
    }
}
View Code

 

posted @ 2013-06-20 10:12  若愚Shawn  阅读(380)  评论(0编辑  收藏  举报