zoukankan      html  css  js  c++  java
  • 面向对象

    继承——————子承父业

    继承是软件(代码)复用的一种形式。使用继承可以复用现有类的数据行为(方法),为其赋予新的功能(方法)从而创建出新类。复用能节省程序开发的时间,能重用经过实践检验和调试的高质量代码,从而提高系统的质量。

    继承的定义和使用

    在现有的类(也称是直接基类,父类)上创建新类(称为派生类,子类)的处理过程称为继承。

    派生类能自动获得基类的除构造函数和析构函数以外的所有成员,可以在派生类中添加新的属性和方法扩展其功能。

    语法为:

    <访问修饰符> class 派生类名:基类名

    {

       类的成员。(类的代码)

    }

    在实际中一个类的对象也是另一个类的对象。

    如:

    教师类和学生类都可以从人这个类派生,而讲师,教授可以从教师类中派生,研究生和本科生可以从学生类派生而得到。

    如:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
    
        public class Person
        {
            private string _id;//声明身份证号码字段
            public string Id//声明身份证号码属性
            {
                get//get访问器,得到身份证号码字段的值
                {
                    return _id;
                }
                set//set访问器设置身份证号码字段的值
                {
                    _id = value;
                }
            }
            private string _name;//声明姓名字段
            public string Name//声明姓名属性
            {
                get
                {
                    return _name;
                }
                set
                {
                    _name = value;
                }
            }
            private int _age;//声明年龄字段
            public int Age//声明年龄属性
            {
                get
                {
                    return _age;
                }
                set
                {
                    _age = value;
                }
            }
            private string _gender;//声明性别字段
            public string Gender//声明性别属性
            {
                get
                {
                    return _gender;
                }
                set
                {
                    _gender = value;
                }
            }
            public Person()//定义无参的构造函数
            { }
            public Person(string name, int age, string gender)//定义3个参数的构造函数
            {
                _name = name;
                _age = age;
                _gender = gender;
            }
            public void Display()//用于输出Person对象的姓名,性别,和年龄信息
            {
                Console.WriteLine("{0}是{1}性,年龄为{2}",this._name,this._gender,this._age);
            }
        }
        public class Student : Person//创建派生类,派生自Person
        {
            private string _class;//定义表示学生所在班级的字段_class
            public string Class//定义获取或设置班级信息的属性Class
            {
                get
                {
                    return _class;
                }
                set
                {
                    _class = value;
                }
            }
            private string _department;//定义学生所属系的字段
            public string Department//定义学生所属系的属性
            {
                get
                {
                    return _department;
                }
                set
                {
                    _department = value;
                }
            }
            private string _no;//定义表示学生学号的字段
            private string No//定义学好的属性
            {
                get
                {
                    return _no;
                }
                set
                {
                    _no = value;
                }
            }
            public Student()//无参构造函数
            { }
            public void Study()//定义派生类独有的方法Studuy,表示学生负有学习的任务
            {
                Console.WriteLine("学生在学校学习!");
            }
        }
       
    
            class Program
            {
                static void Main(string[] args)
                {
    
                    Person objperson = new Person("张三",18,"");//创建Person的对象objperson
                    objperson.Display();//调用Display方法显示对象信息
                    Student objstudent = new Student();//创建Student的对象objstudent
                    objstudent.Name = "李四";
                    objstudent.Age = 18;
                    objstudent.Gender = "";
                    objstudent.Class = "2016软件工程专业1班";
                    objstudent.Display();//访问基类Display方法
                    objstudent.Study();//调用派生类方法
                  
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    运行结果

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
    
        public class Person
        {
            private string _id;//声明身份证号码字段
            public string Id//声明身份证号码属性
            {
                get//get访问器,得到身份证号码字段的值
                {
                    return _id;
                }
                set//set访问器设置身份证号码字段的值
                {
                    _id = value;
                }
            }
            private string _name;//声明姓名字段
            public string Name//声明姓名属性
            {
                get
                {
                    return _name;
                }
                set
                {
                    _name = value;
                }
            }
            private int _age;//声明年龄字段
            public int Age//声明年龄属性
            {
                get
                {
                    return _age;
                }
                set
                {
                    _age = value;
                }
            }
            private string _gender;//声明性别字段
            public string Gender//声明性别属性
            {
                get
                {
                    return _gender;
                }
                set
                {
                    _gender = value;
                }
            }
            public Person()//定义无参的构造函数
            { }
            public Person(string name, int age, string gender)//定义3个参数的构造函数
            {
                _name = name;
                _age = age;
                _gender = gender;
            }
            public void Display()//用于输出Person对象的姓名,性别,和年龄信息
            {
                Console.WriteLine("{0}是{1}性,年龄为{2}",this._name,this._gender,this._age);
            }
        }
        public class Student : Person//创建派生类,派生自Person
        {
            private string _class;//定义表示学生所在班级的字段_class
            public string Class//定义获取或设置班级信息的属性Class
            {
                get
                {
                    return _class;
                }
                set
                {
                    _class = value;
                }
            }
            private string _department;//定义学生所属系的字段
            public string Department//定义学生所属系的属性
            {
                get
                {
                    return _department;
                }
                set
                {
                    _department = value;
                }
            }
            private string _no;//定义表示学生学号的字段
            private string No//定义学好的属性
            {
                get
                {
                    return _no;
                }
                set
                {
                    _no = value;
                }
            }
            public Student()//无参构造函数
            { }
            public void Study()//定义派生类独有的方法Studuy,表示学生负有学习的任务
            {
                Console.WriteLine("学生在学校学习!");
            }
        }
    
        class Teacher : Person
        {
            private string _tid;
            public string Tid
            {
                get
                {
                    return _tid;
                }
                set
                {
                    _tid = value;
                }
            }
            public string _course;
            public string Course
            {
                get
                {
                    return _course;
                }
                set
                {
                    _course = value;
                }
            }
            public void Teaching()
            {
                Console.WriteLine("教师在学校教课");
            }
        }
        public class DoubleStudent : Student
        {
            private string _sndBachelor;
            public string SndBachelor
            {
                get
                {
                    return _sndBachelor;
                }
                set
                {
                    _sndBachelor = value;
                }
            }
            public DoubleStudent()
            {
     
            }
            public void UsaBachelor()
            {
                Console.WriteLine("正在攻读美国Fort Hays 大学学位");
            }
        }
            class Program
            {
                static void Main(string[] args)
                {
                    Teacher objTeacher = new Teacher();//创建Teacher类的对象
                    objTeacher.Name = "Martin";
                    objTeacher.Age = 35;
                    objTeacher.Gender = "";
                    objTeacher.Display();
                    objTeacher.Teaching();
                    Console.WriteLine("DoubleStudent");
                    DoubleStudent objspecial = new DoubleStudent();
                    objspecial.Name = "Bliss";
                    objspecial.Age = 18;
                    objspecial.Gender = "";
                    objspecial.Display();
                    objspecial.Study();
                    objspecial.UsaBachelor(); 
    
                  
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    运行结果

    继承的特性

    1,继承的可传递性

    如果C从B中派生,B又从A中派生,那么C不仅继承了B中声明的成员,同样也继承了A中的成员。派生类是对基类的扩展,在派生类中可以添加新成员,但不能去除已经继承的成员。

    构造函数和析构函数不能被继承。除此以外的其他成员,不论对它们定义了怎样的访问方式,都能被继承。基类中成员的访问方式只能决定派生类能否访问它们。派生类如果定义了与继承而来的成员同名的新成员,就可以覆盖已继承的成员。但这并不意味派生类删除了这些成员,只是不能再访问这些成员。

    2,继承的单一性

    继承的单一性是指派生类只能从一个基类中继承,不能同时继承多个基类。C#不支持类的多重继承,也就是说儿子只能有一个亲生父亲,不能同时拥有多个亲生父亲,多重继承可以通过接口实现。

    3,继承中的访问修饰符

    C#中的访问修饰符有public,protected,private,internal和protected internal等5种,可以使用这些访问修饰符指定5个可访问性级别:public, protected,internal,protected internal和private。在继承时各个访问修饰符的访问权限如表所示

    访问修饰符 类内部 派生类
    public 访问权限不受限制 不受限制
    protected 访问仅限于包含类或从包含类派生的类型 可以访问
    internal 访问仅限于当前项目 可以访问
    protected  internal 访问仅限于从包含类派生的当前项目或类型 可以访问
    private 访问仅限于包含类型 不可访问

    基类中的成员如果使用public修饰,任何类都可以访问;如果用privatc修饰,它将作为私有成员,只有类本身可以访问,其他任何类都无法访问。在C#中,我们使用protected修饰符,使用这个访问修饰符的成员可以被其派生类访问,而不允许其他非派生类访问。

    base和this关键字

    通过上面的介绍可以知道,基类中只能被public,protected,internal修饰的成员才可以被访问,这些成员包括任何基类的字段,属性,方法和索引器,但是基类的构造函数和析构函数是不能被继承的。如果要继承基类的构造函数,必须使用base关键字来实现。C#中的base关键字代表基类,使用base关键字可以调用基类的构造函数,属性和方法。使用base关键字调用基类构造函数的语法如下:

    派生类构造函数:base(参数列表)

    例如:

        public Student(string name,int age,string gender):base(name,age ,gender)//无参构造函数
            { 
    
            }

    使用base关键字调用基类方法的语法如下:

    base.基类方法();

       public void Study()//定义派生类独有的方法Studuy,表示学生负有学习的任务
            {
                Console.WriteLine("学生在学校学习!");
                base.Display();//使用base关键字调用基类方法
            }

    相对于base来说,this关键字是引用类的当前实例。例如:

       public Person(string name, int age, string gender)//定义3个参数的构造函数
            {
               this. _name = name;
               this._age = age;
               this. _gender = gender;
            }

    this关键字引用类的当前实例,还可用做扩展方法的第一个参数的修饰符,this关键字还可以调用自己的构造方法。使用this关键字可以使代码的编写简单化,不容易出错。在类的方法里输入this关键字,在后面输入一个“.”符号后,系统就会把本类所能调用的非静态方法和变量都显示出来供选择,这样可以提高编写代码的效率。

    派生类继承基类的属性和方法,使创建派生类变得简单,可实现代码的重用。继承还有个重要的特性,就是基类对象可以引用派生类对象,也就是派生类对象可以赋值给基类对象。

    如:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
    
       
            public class Person
            {
                private string _id;
                public string Id
                {
                    get
                    {
                       return this._id;
                    }
                    set
                    {
                        this._id=value;
                    }
                }
                private string _name;
                public string Name
                {
                    get
                    {
                        return this._name;
                    }
                    set
                    {
                        this._name=value;
                    }
                }
                private int _age;
                public int Age
                {
                    get
                    {
                        return this._age;
                    }
                    set
                    {
                        this._age=value;
                    }
                }
                private string _gender;
                public string Gender
                {
                    get
                    {
                        return this._gender;
                    }
                    set
                    {
                        this._gender=value;
                    }
                }
                public Person()
                {
    
                }
                public Person(string name,int age,string gender)
                {
                    this._name=name;
                    this._age=age;
                    this._gender=gender;
                }
                public void Display()
                {
                    Console.WriteLine("{0}是{1}性,年龄为{2}",this._name,this._gender,this._age);
                }
            }
            public class Student:Person
            {
                private string _class;
                public string Class
                {
                    get
                    {
                        return _class;
                    }
                    set
                    {
                        _class=value;
                    }
                }
                private string _department;
                public string Departmtent
                {
                    get
                    {
                        return this._department;
                    }
                    set
                    {
                        this._department=value;
                    }
                }
                private string _no;
                public string No
                {
                    get
                    {
                        return this._no;
                    }
                    set
                    {
                        this._no=value;
                    }
                }
                public Student()
                {
    
                }
                public Student(string name,int age,string gender):base(name,age,gender)
                {
    
                }
                public void Study()
                {
                    Console.WriteLine("学生在学习呢!");
                }
            }
    
            class Program
            {
                static void Main(string[] args)
                {
                    Person objPerson = new Person("刘六",18,"");
                    Console.WriteLine("基类Person对象的Display方法");
                    objPerson.Display();
                    Student objstudent = new Student("王七",18,"");
                    objstudent.Class = "2016软件工程专业1班";
                    Console.WriteLine("派生类调用基类Person对象的Displauy方法:");
                    objstudent.Display();
                    Console.WriteLine("派生类调用自己的Study方法:");
                    objstudent.Study();
                    Console.WriteLine("基类对象引用派生类实例");
                    Person person = new Person();
                    person = objstudent;
                    ((Student)person).Study();
                  
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    运行结果

     面向对象——多态

    "多态“最早用于生物学,指同一种族的生物体具有相同的特性。

    比如青蛙小的时候是蝌蚪,长大了就是青蛙,同是一种生物但是有不同的表现形式。

    C#中,多态的定义是:同一操作作用于不同的类的对象,不同的类的对象进行不同的执行,最后产生不同的结果。

    多态的实现

    C#中支持基于接口的多态和基于继承的多态,基于继承的多态设计在基类中定义方法,并在派生类中重写方法。多态和重写是紧密联系的,重写是实现多态的重要手段,重写基类方法就是修改它的实现,或者说在派生类中对继承的基类方法的重新编写。在基类中用virtual关键字声明的方法(叫做虚拟方法)在派生类中可以重写,虚拟方法语法如下;

    访问修饰符 virtual 返回类型 方法名()

    {

       //方法体

    }

    在派生类中使用override关键字来声明重写,以实现对基类中虚拟方法的修改或重新编写。

    例如:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
    
       
            public class Person
            {
                private string _id;
                public string Id
                {
                    get
                    {
                       return this._id;
                    }
                    set
                    {
                        this._id=value;
                    }
                }
                private string _name;
                public string Name
                {
                    get
                    {
                        return this._name;
                    }
                    set
                    {
                        this._name=value;
                    }
                }
                private int _age;
                public int Age
                {
                    get
                    {
                        return this._age;
                    }
                    set
                    {
                        this._age=value;
                    }
                }
                private string _gender;
                public string Gender
                {
                    get
                    {
                        return this._gender;
                    }
                    set
                    {
                        this._gender=value;
                    }
                }
                public Person()
                {
    
                }
                public Person(string name,int age,string gender)
                {
                    this._name=name;
                    this._age=age;
                    this._gender=gender;
                }
                public virtual  void Display()
                {
                    Console.WriteLine("{0}是{1}性,年龄为{2}",this._name,this._gender,this._age);
                }
            }
            public class Student:Person
            {
                private string _class;
                public string Class
                {
                    get
                    {
                        return _class;
                    }
                    set
                    {
                        _class=value;
                    }
                }
                private string _department;
                public string Departmtent
                {
                    get
                    {
                        return this._department;
                    }
                    set
                    {
                        this._department=value;
                    }
                }
                private string _no;
                public string No
                {
                    get
                    {
                        return this._no;
                    }
                    set
                    {
                        this._no=value;
                    }
                }
                public Student()
                {
    
                }
                public Student(string name,int age,string gender):base(name,age,gender)
                {
                    this._class = "三班";
                    this._department = "建筑系";
                    this._no = "141020";
                }
                public void Study()
                {
                    Console.WriteLine("学生在学习呢!");
                }
                public override void Display()
                {
                    base.Display();
                    Console.WriteLine("学生在学习呢!");
                }
            }
    
            class Program
            {
                static void Main(string[] args)
                {
                  
                   
                    Person objPerson = new Person("刘六",18,"");
                    Console.WriteLine("基类Person对象的Display方法");
                    objPerson.Display();
                    Student objstudent = new Student("王七",18,"");
                    objstudent.Class = "2016软件工程专业1班";
                    Console.WriteLine("Student对象的Display方法");
                    objstudent.Display();
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    方法的重载,重写和隐藏

    在基类和派生类中可以存在同名方法,这些同名的方法可以为重载,重写和隐藏等3种类型。

    1.重载

    重载是在同一作用域内发生的(比如一个类里面),定义一系列同名方法,但是方法的参数列表不同,就是签名不同,签名由方法名和参数组成。通过传递不同的参数来决定到底调用哪一个同名方法,返回值类型不同不能构成重载,因为签名不包括返回值。

    2.重写

    基类方法中使用virtual关键字声明的方法和派生类中使用override关键字声明的方法名称相同,参数列表也相同,就是基类方法和派生类方法的签名相同,实现了派生类重写基类中的同名方法。

    3.隐藏

    基类中的方法不声明为virtual(默认为非虚方法),在派生类中声明与基类同名时,需使用new关键字,以隐藏基类同名的方法。

    例如:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
    
       
            public class Person
            {
                
                public virtual  void Display()
                {
                    Console.WriteLine("这是一个人");
                }
                public void Display(string name)
                {
                    this.Display();
                    Console.WriteLine("这个人的名字叫{0}",name);
                }
            }
            public class Student:Person
            {
               
                public override void Display()
                {
                    base.Display();
                    Console.WriteLine("学生在学习呢!");
                }
                public new void Display(string name)
                {
                    Console.WriteLine("这个方法隐藏了基类的方法");
                }
            }
    
            class Program
            {
                static void Main(string[] args)
                {
                  
                   
                 
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    统一的接口—————接口

    接口是面向对象编程的一个重要技术,在C#中负责实现多重继承。一个接口定义一个协议,实现接口的类或结构必须遵守其协定。

    接口的定义

    接口是用来描述一种程序的规定,可定义属于任何类或结构的一组相关行为。接口由方法,属性,事件,索引器或这4种成员类型的任何组合构成。

    接口不能包含常数,字段,运算符,实例构造函数,析构函数或类型,也不能包含任何种类的静态成员。

    接口的成员一定是公共的。

    定义接口的语法如下:

    <访问修饰符>interface 接口名

    {

    //接口的主体

    }

    接口不能包含其所定义的成员的任何实现语句,接口只指定实现该接口的类或必须提供的成员。

    接口的实现

    定义了接口后,就要在类或结构中实现。C#中通常把派生类和基类的关系称为继承,类和接口的关系称为实现。实现接口的语法和继承类一样,都有“:”,接口中的方法在类中实现时不是重载,不需要使用override关键字。

    接口中不能定义构造函数,所以接口不能实例化。

    例如:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
        interface IPoint
        {
            int x { get; set; }
            int y { get; set; }
        }
        class Point : IPoint
        {
            private int px;
            private int py;
            public Point(int x, int y)
            {
                px = x;
                py = y;
            }
            public int x
            {
                get
                {
                    return px;
                }
                set
                {
                    py = value;
                }
            }
            public int y
            {
                get
                {
                    return py;
    
                }
                set
                {
                    py = value;
                }
            }
    
        }
            class Program
            {
                static void Main(string[] args)
                {
    
                    Point p = new Point(5, 30);
                    Console.Write("新创建的Point点的坐标是:");
                    Console.WriteLine("x={0},y={1}",p.x,p.y);
                 
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    再次进行扩展

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
        interface IPerson
        {
            void DoWork();//表示person在做工作
    
            void DoExercise();//表示person锻炼身体
        }
        public class Person : IPerson
        {
            private string _id;
            public string Id
            {
                get
                {
                    return _id;
                }
                set
                {
                    _id = value;
                }
                    
            }
            private string _name;
            public string Name
            {
                get
                {
                    return _name;
                }
                set
                {
                    _name = value;
                }
            }
            private int _age;
            public int Age
            {
                get
                {
                    return _age;
    
                }
                set
                {
                    _age = value;
                }
            }
            private string _gender;
            public string Gender
            {
                get
                {
                    return _gender;
                }
                set
                {
                    _gender = value;
    
                }
            }
            public Person()
            {}
            public Person(string name, int age, string gender)
            {
                this._name = name;
                this._age = age;
                this._gender = gender;
            }
            public void DoWork()
            {
                Console.WriteLine("{0}每天的任务是工作",this._name);
            }
            public void DoExercise()
            {
                Console.WriteLine("{0}每天下午参加体育锻炼",this._name);
            }
            public void Diplay()
            {
                Console.WriteLine("{0}是{1}性,年龄为{2}",this._name,this._gender,this._age);
            }
     
        }
       
            class Program
            {
                static void Main(string[] args)
                {
    
                    Person p1 = new Person("Johnson",28,"");
                    p1.Diplay();
                    p1.DoWork();
                    p1.DoExercise();
                 
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    接口的继承

    C#中的派生类只有一个基类,不支持类的多重继承,但可以继承多个接口,通过接口实现多继承。

    其实接口就是为实现多继承产生的。在C#中接口可以多继承,接口之间可以相互继承,普通类和抽象类可以继承自接口。一个类可以同时继承一个类和多个接口,但是接口不能继承类。

    抽象类和抽象方法

    抽象类:简单的说就是用来描述共性的类就是抽象类,(抽象类是对类的抽象,类是对对象的抽象)抽象类中不考虑具体的实现,只确定必须具有的行为,即确定抽象方法。

    包含抽象方法的类就是抽象类,抽象类和抽象方法声明使用abstract关键字。语法如下:

    <访问修饰符>abstract class 抽象类名

    {

       <访问修饰符> abstract 返回类型 方法名();

    }

    实现抽象方法

    C#中通过方法重写来实现抽象方法。当一个抽象基类派生一个派生类时,派生类将继承基类的所有特征,重新实现所有的抽象方法。在派生类中实现基类的抽象方法,是使用override关键字来重写基类方法。

    例如:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
        public abstract class Employee
        {
            public abstract void Display();
        }
        public class Manager : Employee
        {
            private string name;
            public Manager(string name)
            {
                this.name = name;
            }
            public override void Display()
            {
                Console.WriteLine("Name:"+name);
            }
        }
            class Program
            {
                static void Main(string[] args)
                {
                    Manager obj = new Manager("Johnson");
                    obj.Display();
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    接口,类和抽象类

     一个类可以同时继承类和接口,或者抽象类和接口,抽象类和类不能在一个类的继承列表中同时出现。如果派生类同时继承类或抽象类和接口,一定要把类或者抽象类写在前面,接口写在后面,类名和接口名用“,”隔开,接口没有先后顺序。每一种继承都要根据各自的规则去实现。

    接口与抽象类的区别:

    1,抽象类是一个不完全的类,需要通过派生类来完善它。

    2,接口只是对类的约束,它仅仅承诺了类能够调用的方法。

    3,一个类一次可以实现若干个接口。但一个类只能继承一个基类。

    4,抽象类只需派生类实现它的抽象方法,接口要求必须实现它的所有成员。在实际编程中,接口的使用要比抽象类广泛得多。

    密封类

    与抽象类相反的是,C#支持创建密封类,密封类是不能当做基类的类。其他的类不能从此类派生,从而保证了密封类的密封性和安全性。在C#中使用sealed关键字创建密封类。

    如:

    public selaed class Animal

    {

        public Animal()

         {

                  Console。WriteLine(“Animal被构造”);

         }

    }

    设计类的时候,通常情况下是不需要将类设置为密封类的,因为密封类会让类的扩展性非常差,这个类也无法再次扩展和派生。但是出于某种目的,当程序块只需要完成某些特定的功能或者在商业上为保密,就可以使用密封类对类进行密封,以保证类的可靠性。

    委托,事件和索引器

    委托和事件是C#中两个比较复杂的概念。

    委托

    委托也叫代理,就是把事情交付给别人去办,如委托律师代理打官司。

    C#中如果将一个方法委托给一个对象,这个对象就可以全权代理这个方法的执行。使用委托首先要定义委托,声明委托能代理什么类型的方法,定义委托的语法如下:

    <访问修饰符> delegate 返回类型 委托名();

    从上面不难看出定义委托和定义方法类似。委托没有具体的实现体,委托能够代表什么样的方法由它的返回值类型和参数列表决定。如定义如下委托:

    public delegate void StuDelegate(string name);

    使用stuDelegate委托代表的只可以是没有返回值,且参数为一个字符串的方法。

    定义了委托之后就要使用委托,首先要实例化委托。实例化委托就是将其指向某个方法,即调用委托的构造函数,并将相关联的方法作为参数传递,然后通过调用委托,执行相关方法的代码,实现委托。

    如:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
        class Test
        {
            public static bool SortArray(int[] array)
            {
                for (int i = array.GetUpperBound(0); i >= 0; i--)
                {
                    for (int j = 0; j <= i; j++)
                    {
                        if (array[j] <= array[i])
                        {
                            Swap(ref array[j], ref array[i]);
                        }
     
                    }
                   
                } 
                return true;
            }
            static void Swap(ref int x, ref int y)
            {
                int temp = x;
                x = y;
                y = temp;
            }
        }
       
            class Program
            {
                public delegate bool SortDelegate(int[] x);
    
                static void Main(string[] args)
                {
                    int[] arr = new int[] { 8, 9, 5, 7, 2, 1, 4, 5, 6 };
                    Console.WriteLine("排顺序前的数组元素:");
                    foreach (int i in arr)
                    {
                        Console.WriteLine("{0}",i);
     
                    }
                    SortDelegate mydelegate;
                    mydelegate = new SortDelegate(Test.SortArray);
                    mydelegate(arr);
                    Console.WriteLine("排顺序后的数组元素:");
                    foreach (int i in arr)
                    {
                        Console.WriteLine("{0}", i);
    
                    }
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

     使用Lambda表达式运行结果不变

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
       
       
            class Program
            {
                public delegate bool SortDelegate(int[] x);
    
                static void Main(string[] args)
                {
                    int[] arr = new int[] { 8, 9, 5, 7, 2, 1, 4, 5, 6 };
                    Console.WriteLine("排顺序前的数组元素:");
                    foreach (int i in arr)
                    {
                        Console.WriteLine("{0}",i);
     
                    }
                    SortDelegate mydelegate = array =>
                    {
                        for (int i = array.GetUpperBound(0); i >= 0; i--)
                        {
                            for (int j = 0; j <= i; j++)
                            {
                                if (array[j] <= array[i])
                                {
                                    int temp = array[j];
                                    array[j] = array[i];
                                    array[i] = temp;
                                }
                            }
                        }
                        return true;
                    };
                    mydelegate(arr);
                 
                    Console.WriteLine("排顺序后的数组元素:");
                    foreach (int i in arr)
                    {
                        Console.WriteLine("{0}", i);
    
                    }
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    索引器

    索引器允许类或结构的实例就像数组一样进行索引。索引器类似于属性,不同之处在于它们的访问器采用的参数。索引器主要用于封装内部集合或数组的类中。索引器类似于字典中的检索,在字典中可以进行拼音检索和部首检索等方式查找汉子,索引器可以根据需要设定不同的检索方式快速查找类或结构的实例。索引器表示法不仅简化了客户端应用程序的语法,还使其他开发人员能够更加直观地理解类及其用途。要声明类或结构上的索引器,应使用关键字this如:

    public int this[int index]

    {

    }

    例如:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
    
        class DayCollection
        {
            string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };
            private int GetDay(string testDay)
            {
                int i = 0;
                foreach (string day in days)
                {
                    if (day == testDay)
                    {
                        return i;
                    }
                    i++;
                }
                return -1;
            }
            public int this[string day]
            {
                get
                {
                    return GetDay(day);
                }
            }
        }
       
       
            class Program
            {
                static void Main(string[] args)
                {
                    DayCollection week = new DayCollection();
                    Console.WriteLine(week["Fri"]);
                    Console.WriteLine(week["Invalid Day"]);
                    
                    Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    运行结果为:5,-1;

    再例如:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
    
        class TempRecord
        {
            private float[] temps = new float[10]{56.2F,56.7F,56.5F,56.9F,58.8F,
                                              61.3F,65.9F,62.1F,59.2F,57.5F};
            System.DateTime date { get; set; }
            public int Length
            {
                get { return temps.Length; }
            }
            public float this[int index]
            {
                get
                {
                    return temps[index];
                }
                set
                {
                    temps[index] = value;
                }
            }
        }
       
       
            class Program
            {
                static void Main(string[] args)
                {
                    TempRecord temp = new TempRecord();
                    temp[3] = 58.3F;
                    temp[5] = 60.1F;
                    for (int i = 0; i < 10; i++)
                    {
                        if (i < temp.Length)
                        {
                            Console.WriteLine("元素{0}={1}", i, temp[i]);
                        }
                        else
                        {
                            Console.WriteLine("索引值{0}超出范围",i);
                        }
                    }
    
                        Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    事件

    事件是C#中的一个高级概念,是操作发生时允许执行特定于应用程序的代码的机制,事件要么在相关联的操作发生前发生(事前事件)要么在操作发生后发生(事后事件)。

    例如,当用户单击窗口中的按钮时,将引发一个事后事件,以允许执行特定于应用程序的方法。

    类和对象可以通过事件向其他类或对象通知发生的相关事情。发送(或引发)事件的类称为“发行者”,接受(或处理)事件的类称为“订户”。在典型的C#Windows 窗体或web应用程序中,可以订阅由控件(如按钮和列表框)引发的事件。如在考场上老师说“开始考试”,学生就开始答卷,其中老师说的“开始答卷”是事件,“学生开始答卷”是这个事件引发的动作。老师是事件的发行者。学生是事件的订户。

    定义和使用事件一般有下面几个步骤

    1,在一个类中声明关于事件的委托。

    public delegate void 事件类型名称(object serder,EventArgs e);

    事件的类型名称建议用EventHandler结尾。如果想自定义事件的参数EventArgs,可以用EventArgs类派生自己的事件参数类,也可以没有参数。

    2,在类中声明事件。使用步骤1的delegate做为事件的类型。

    public event 事件类型名称 事件名称;

    3,在类中需要引发事件的方法中,编写引发事件的方法。

    事件名称(this,new EventArgs());或者

    if(事件名称!=null) 事件名称(this,new EventArgs());

    4,订阅事件,当事件发生时通知订户。

    带有事件的类的实例.事件名称+=new 事件名称(事件处理方法名称);

    5,编写事件处理方法

    public void 事件处理方法名称(object sender ,EventArgs e)

    {

    要添加的代码

    }

    6,在适当的条件下触发事件,即需要调用步骤3中的引发事件的方法。

    范例:事件的定义和使用

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
    
       public class Heater
        {
           private int temperature;
           public delegate void BoilHandler(int param);
           public event BoilHandler BoilEvent;
           public void BoilWater()
           {
               for (int i = 0; i <= 100; i++)
               {
                   temperature = i;
                   if (temperature > 96)
                   {
                       if (BoilEvent != null)
                       {
                           BoilEvent(temperature);
                       }
                   }
               }
           }
        }
       public class Alarm
       {
           public void MakeAlert(int param)
           {
               Console.WriteLine("Alarm:滴滴滴,水已经{0}度了", param);
           }
       }
       public class Display
       {
           public static void ShowMsg(int param)
           {
               Console.WriteLine("Display:水快烧开了,当前温度:{0}度",param);
           }
       }
            class Program
            {
                static void Main(string[] args)
                {
                    Heater heater = new Heater();
                    Alarm alarm = new Alarm();
                    heater.BoilEvent += alarm.MakeAlert;
                    heater.BoilEvent += Display.ShowMsg;
                    heater.BoilWater();
    
                        Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    运行结果为:

     把Heater类不变,去掉Alarm类和Display类,使用匿名方法订阅事件

    如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication2
    {
    
       public class Heater
        {
           private int temperature;
           public delegate void BoilHandler(int param);
           public event BoilHandler BoilEvent;
           public void BoilWater()
           {
               for (int i = 0; i <= 100; i++)
               {
                   temperature = i;
                   if (temperature > 96)
                   {
                       if (BoilEvent != null)
                       {
                           BoilEvent(temperature);
                       }
                   }
               }
           }
        }
     
            class Program
            {
                static void Main(string[] args)
                {
                    Heater heater = new Heater();
                    heater.BoilEvent += delegate(int param)
                    {
                        Console.WriteLine("Alarm:嘀嘀嘀,水已经{0}度了。", param);
                    };
                    heater.BoilEvent += delegate(int param)
                    {
                        Console.WriteLine("Display:水烧开了,当前温度为:{0}度",param);
                    };
                    heater.BoilWater();
    
                        Console.ReadKey();
    
                }
    
          
    
    
            }
    
    
        }

    运行结果与之前相同。

  • 相关阅读:
    开发了那么多项目,你能自己手写个健壮的链表出来吗?【华为云技术分享】
    高性能Web动画和渲染原理系列(3)——transform和opacity为什么高性能【华为云技术分享】
    pringBoot-MongoDB 索引冲突分析及解决【华为云技术分享】
    成为高手前必懂的TCP干货【华为云技术分享】
    Python爬虫从入门到精通——基本库re的使用:正则表达式【华为云技术分享】
    【我的物联网成长记2】设备如何进行选型?【华为云技术分享】
    多云架构落地设计和实施方案【华为云技术分享】
    dom的节点操作
    节点访问关系
    封装class类--分割类名后
  • 原文地址:https://www.cnblogs.com/lizanqirxx/p/5426738.html
Copyright © 2011-2022 走看看