C-sharp面向对象 
面向对象两个重要概念:类和对象 
面向对象三大特征:封装、继承和多态 
  类和对象 
例子,我们定义一个Person类代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo {     internal class Person   // 类首     {         // 类体         //成员变量         public string name;         public int age;         //成员方法         public void Speak()         {             Console.WriteLine("我是{0},我今年{1}岁", name, age);         }     } } 
 
然后在main方法中使用这个类,即在Program.cs文件中输入代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo {     class Program     {         static void Main(string[] args)         {             Person person = new Person();   // 实例化对象             person.name = "tom";             person.age = 19;             person.Speak();             Console.ReadLine();         }     } } 
 
  类的成员 
类是一种引用数据类型。类的成员有:
  构造方法 
构造方法名和类名相同 
构造方法没有返回值类型 
构造方法名前的权限修饰符通常使用public 
 
构造方法的重载 ,例子:
在Person类中代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo {     internal class Person   // 类首     {         // 类体         //成员变量         public string name;         public int age;         //成员方法         public Person()     // 定义无参构造方法         {             Console.WriteLine("无参构造方法调用了");         }         public Person(string name)     // 定义有参构造方法         {             Console.WriteLine("有参构造方法调用了,name={0}",name);         }         public void Speak()         {             Console.WriteLine("我是{0},我今年{1}岁", name, age);         }     } } 
 
在Program.cs中编写代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo {     class Program     {         static void Main(string[] args)         {             Person person1 = new Person();   // 实例化对象(无参构造方法)             Person person2 = new Person("tom"); // 有参构造方法             Console.ReadLine();         }     } } 
 
  属性 
属性是一种与当前对象关联的、主要用于访问类中某一数据成员 的机制 
为了防止数据被其他人随意修改,把字段声明为私有访问权限(封装性 ) 
 
属性包括属性头和属性体。属性头(属性名),属性体(get和set)
例子,在Person类中输入代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo {     internal class Person   // 类首     {         // 类体         //声明字段         private string name;         private int age;         // 声明属性         // 通过快捷键自动生成的get和set         public string Name { get => name; set => name = value; }         public int Age { get => age; set => age = value; }         //public string Name         //{         //    get { return name; }    // 读操作         //    set { name = value; }   // 写操作         //}         //public int Age         //{         //    get { return age; }          //    set         //    {         //        if (age<0)         //        {         //            Console.WriteLine("年龄输入不合法!");         //        }         //        else         //        {         //            age = value;         //        }         //    }         //}         //// 自动属性         //public char Gender { get; set; }         //成员方法         public void Speak()         {             Console.WriteLine("我是{0},我今年{1}岁", Name, Age);         }     } } 
 
其中快速生成get和set的快捷键为Ctrl R E ,自动生成的代码中的=>是Lambda表达式,可自行查看。
关于C#自动属性可自行查看。
属性和方法都属于类的方法成员 ,都可以完成对类体中数据成员的访问。不同之处为:
属性名后不需要(),方法名后必须有()  
属性不能指定参数,方法可以指定参数  
属性不能使用void类型,方法可以使用void类型  
 
  修饰符 
访问修饰符(C# 编程指南) ,C#的类修饰符和成员修饰符 
类的常用修饰符:
public		表示访问权限不受限制 
abstract    表示这是一个抽象类  
sealed       表示这是一个密封类(不能被继承)  
 
类的成员常用修饰符:
public		表示公有成员,访问不受限制 
private      表示私有成员,只能在成员所在类内访问。(类成员的默认访问权限)  
protected  表示受保护成员,只能在成员所在类内和子类访问  
static          表示静态成员变量,只能使用类名访问该成员。不用static修饰的成员称为实例成员,需要使用类的实例(即对象)进行访问  
 
 
  继承 
菜鸟教程 
继承是通过已有类创建新类的机制。
被继承的已有类称为超类(super class,又称基类、父类) 
继承得到的新类称为扩展类(expansion class,又称子类、派生类) 
 
在C#的继承中:
例子,我们先定义一个Person父类,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo02 {     class Person     {         // 类体         //声明字段         private string name;         private int age;         // 声明属性         // 通过快捷键自动生成的get和set         public string Name { get => name; set => name = value; }         public int Age { get => age; set => age = value; }         //成员方法         public void Speak()         {             Console.WriteLine("我是{0},我今年{1}岁", Name, Age);         }     } } 
 
然后创建Student类,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo02 {     class Student:Person    // Student类继承了Person类     {     } } 
 
然后在main方法中输入代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo02 {     class Program     {         static void Main(string[] args)                      Student student = new Student();             student.Name = "tom";             student.Age = 19;             student.Speak();             Console.ReadLine();         }     } } 
 
可以看到Student类以及可以继承Person类的成员变量和方法了。
关于构造方法的继承,例子如下:
先在父类Person中添带参构造方法如下:
1 2 3 4 5 6 public Person(string name,int age)         {             Name = name;             Age = age;             Console.WriteLine("调用了父类有参构造函数");         } 
 
然后在子类Student类中添加代码如下:
1 2 3 4 5 6 7 class Student:Person    // Student类继承了Person类     {         public Student(string name,int age) : base(name, age)         {             Console.WriteLine("调用了子类的有参构造函数");         }     } 
 
然后在main方法中执行代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo02 {     class Program     {         static void Main(string[] args)         {             Student student = new Student("tom",19);             student.Speak();             Console.ReadLine();         }     } } 
 
结果为:
(具体可自行查看)
  抽象类和抽象方法 
使用abstract关键字作为修饰符的类和方法即为抽象类和抽象方法
抽象类本身不能被实例化,即不能直接创建抽象类的对象  
抽象类只能作为父类,用于继承  
当某个抽象类被继承得到的子类作为非抽象类后,该子类可以正常进行实例化操作  
抽象方法只有方法头,没有方法体。即没有方法的具体实现  
每个抽象方法的方法声明以分号;结束  
 
抽象类和抽象方法的关系:
抽象类可以不包含抽象方法 
如果某个类中包含了抽象方法,则该类必须声明为抽象类 
当继承抽象类的子类是非抽象类时,则必须在子类中为抽象父类中的抽象方法提供具体的实现  
在实现抽象方法时,需要在方法头使用override关键字  
 
例子:
我们声明一个抽象类Animal,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo03 {      abstract class Animal     {         public abstract void Bark();    // 抽象方法         public void Sleep()         // 非抽象方法         {             Console.WriteLine("睡着了");         }     } } 
 
然后在创建其子类Dog,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo03 {     class Dog : Animal     {         public override void Bark()     // 实现抽象方法         {             Console.WriteLine("狗再叫");         }     } } 
 
(在子类中重写抽象方法快捷键:Alt+Enter)
执行代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo03 {     class Program     {         static void Main(string[] args)         {             Dog dog = new Dog();             dog.Bark();             Console.ReadLine();         }     } } 
 
  sealed密封类 
sealed(C# 参考) 
sealed关键字来修饰类、实例方法和属性作用如下:
类的声明使用sealed修饰,表示该类不允许被继承  
方法声明使用sealed修饰,表示方法重写了父类的方法,但不允许再被其子类重写  
属性声明使用sealed修饰,表示属性重写了父类的属性,但不允许再被其子类重写  
 
  接口  
菜鸟教程 
接口是完全的抽象成员的集合,即接口体中只能包含抽象成员(抽象方法、抽象属性等)  
接口默认的成员默认为公有、抽象成员,因此接口的成员声明前不能添加 public和abstract关键字  
一个类可以实现多个接口,接口的实现使用冒号:  
使用interface关键字声明接口  
 
(单继承多实现)
例子:
创建一个接口ISleepable,代码如下:(接口命名一般在前面加I)
1 2 3 4 5 6 7 8 9 10 11 12 13 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo04 {     interface ISleepable     {          void Sleep();     } } 
 
然后创建People类来实现ISleepable接口,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo04 {     class PeoPle : ISleepable     {         public void Sleep()         {             Console.WriteLine("人可以睡觉");         }     } } 
 
执行代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo04 {     class Program     {         static void Main(string[] args)         {             People people = new People();             people.Sleep();             Console.ReadLine();         }     } } 
 
再来一个例子 :有三类人员教师、学生和程序员,他们都有姓名、年龄等属性,都可以通过Sleep方法睡觉,其中教师可以教学。
我们分别创建Teacher、Student、Coder类,并让其继承父类People。
People类代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo04 {     class People : ISleepable     {         private string name;         private int age;         public string Name { get => name; set => name = value; }         public int Age { get => age; set => age = value; }         public void Sleep()         {             Console.WriteLine("{0}睡觉了",Name);         }     } } 
 
创建ITeach接口,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo04 {     interface ITeach     {         void Teach();     } } 
 
创建Teacher类代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo04 {     class Teacher : People, ITeach      // 继承People类,实现ITeach接口     {         public void Teach()         {             Console.WriteLine("{0}开始教课了", Name);         }     } } 
 
然后分别创建Student类和Coder类,关键部分代码如下:
1 2 3 4 5 6 namespace demo04 {     class Student:People     {     } } 
 
1 2 3 4 5 6 namespace demo04 {     class Coder:People     {     } } 
 
执行代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo04 {     class Program     {         static void Main(string[] args)         {             Teacher teacher = new Teacher();             Student student = new Student();             Coder coder = new Coder();             teacher.Name = "老师";             student.Name = "学生";             coder.Name = "程序员";             teacher.Sleep();             teacher.Teach();    // 实现了ITeach接口,即可以调用Teach方法             student.Sleep();             coder.Sleep();             Console.ReadLine();         }     } } 
 
例子3:两个接口中的抽象方法同名的情况 
创建两个接口IMyInterface1和IMyInterface2,关键部分代码如下:
1 2 3 4 5 6 7 namespace demo04 {     interface IMyInterface1     {         void Print();     } } 
 
1 2 3 4 5 6 7 namespace demo04 {     interface IMyInterface2     {         void Print();     } } 
 
然后创建MyClass类,来实现这两个接口,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo04 {     class MyClass : IMyInterface1, IMyInterface2     {         void IMyInterface1.Print()         {             Console.WriteLine("实现了IMyInterface1中的Print方法");         }         void IMyInterface2.Print()         {             Console.WriteLine("实现了IMyInterface2中的Print方法");         }     } } 
 
(Alt+Enter,选择显示实现接口 )
然后执行代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo04 {     class Program     {         static void Main(string[] args)         {             IMyInterface1 interface1 = new MyClass();   // 多态             IMyInterface2 interface2 = new MyClass();   // 多态             interface1.Print();             interface2.Print();             Console.ReadLine();         }     } } 
 
  多态 
菜鸟教程 
多态是同一个行为具有多个不同表现形式或形态的能力。
多态性 意味着有多重形式。在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"。
多态性可以是静态的或动态的。在静态多态性 中,函数的响应是在编译时发生的。在动态多态性 中,函数的响应是在运行时发生的。
在 C# 中,每个类型都是多态的,因为包括用户定义类型在内的所有类型都继承自 Object。
 
(多态:子类对象父类声明 )
多态主要表现为:方法重载和方法重写(override) 
方法重载:在一个类中包含名字相同 但参数类型不同 的多个方法 
方法重写:如果父类提供的功能不能满足要求,则可以在子类中重新定义
在父类中如果想让某个方法被子类重写,可以使用virtual关键字将方法声明为虚方法,然后就可以在子类中使用override关键字重写该方法  
在C#中方法默认是非虚拟的即不能被重写(若要重写需要virtual关键字) 
virtual不能和static同时使用 
virtual不能和private同时使用 
重写方法的名称、参数、类型、返回值必须与原虚方法完全一样 
 
 
 
例子:创建一个父类Animal,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo05 {     class Animal     {         public virtual void Bark()         {             Console.WriteLine("动物在叫");         }     } } 
 
然后创建其子类Dog类和Cat类,关键部分代码如下:
1 2 3 4 5 6 7 class Dog:Animal {     public override void Bark()     {         Console.WriteLine("狗在叫");     } } 
 
1 2 3 4 5 6 7 class Cat:Animal {     public override void Bark()     {         Console.WriteLine("猫在叫");     } } 
 
执行代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace demo05 {     class Program     {         static void Main(string[] args)         {             // 里氏替换原则             Animal animal1 = new Dog();     // 多态             animal1.Bark();             Animal[] arrAnimla = { new Dog(), new Cat()};             for (int i = 0; i < arrAnimla.Length; i++)             {                 arrAnimla[i].Bark();             }             //// 不使用多态             //Animal animal = new Animal();             //Dog dog = new Dog();             //Cat cat = new Cat();             //animal.Bark();             //dog.Bark();             //cat.Bark();             Console.ReadLine();         }     } }