C#面向对象的三大特征:

封装、继承、多态

封装:

保证对象自身数据的完整性和安全性

1.完整性:封装就是把一些散的代码包装起来,让他们共同去完成一个功能

 如:类、属性、方法都是封装的一种形式

2.安全性:如:我们在创建一个对象或调用一个方法时,只需要实例化一个类对象

 或调用一个方法名就可以完成我们需要的功能,而他内部是怎么实现的,我们无法看到

继承:

C#继承的语法:

public class 子类:父类

{

//继承使用 : 符号

}

概念:

建立类之间的关系(父类与子类),实现代码复用,方便系统的扩展

1.在继承中分为父类(基类)和子类(派生类),也就是说当子类继承了父类以后,

 那么子类就拥有了父类中非private的成员(属性、方法等)

例子:

学生类 有姓名、年龄...

员工类 有姓名、年龄...

那么如果这个时候,我们还要添加男人类、女人类等,

那是不是又要去写姓名 和 年龄等这些属性...这样就会很麻烦

然而 学生类和员工类 他们都共有 姓名、年龄这两个属性

之所以,他们都有这两个属性是因为他们都属于人类

所以这个时候我们就可以把他们共有的属性等提取出来共同封装

在一个Person类中,然后让学生类和员工类都继承Person类

这样,学生类和员工类就都拥有了姓名和年龄这两个属性,

他们共有的属性、方法就交给了Person类来管理,而他们只需要管理

自己特有的属性、方法就可以了

这样做的好处就是实现了代码的复用,方便了系统的扩展,

如:

以后我们还要再添加一个男人类或者女人类等,

就不用再去写姓名、年龄等这些他们共有的成员了,只需要继承Person类就可以了,

同样,如果要添加一个他们共有的成员时,只需要在父类Person中添加就可以了

而不必去在他们每个类中都去添加新增的成员。

例子:

  public class Person //人类(这里他是父类)

  {

       public string Name{get;set;} //姓名

       public int Age{get;set;}     //年龄

  }

  public class Student:Person  //学生类 继承 人类

  {

       //当Student继承了Person后,Student就自动拥有了Person类的非private成员

  }

  public class Employee:Person  //员工类 继承 人类

  {

       //当Employee继承了Person后,Employee就自动拥有了Person类的非private成员

  }

  当我们创建一个Student对象和Employee对象时:

       Student stu = new Student();

       Employee emp = new Employee();

  就可以使用:

       stu.Name="张三";

       stu.Age = 20;

       emp.Name = "李四";

       emp.Age = 30;

   这就是因为他们都继承了Person类的原因


2.继承要符合 "子类 is a 父类" 的关系,就是说 子类是一个父类

例子:同上面所说,要想实现继承,就必须要符合 子类 is a 父类的关系,

 如:学生是一个人,学生 is a 人  员工是一个人 员工 is a 人


3.继承的单根性,在C#中一个子类只能继承一个父类(就像一个儿子不能拥有多个父亲一样)


4.子类可以替换父类并且出现在父类能够出现的任何地方,且程序的行为不会发生变化,但是

 反过来,父类对象不能替换子类对象,这种特性被称作 "里氏替换原则(Liskor Subsitution Principle)"

例子:

上面的例子创建对象也可以这样写:

Person p1 = new Student();

Person p2 = new Employee(); //里氏替换原则

而下面这样写就会报错:

Student stu = new Person();

Employee emp = new Person();  //报错

里氏替换原则中可以使用 is 和 as 操作符

is:用于去判断一个类型是否是给定的类型,返回bool值

如:p1 is Student  //判断p1是否是Student类型 true:是 false:不是

as:用于把一个类型转换为另一个类型,类似于强制转换,但是在强制转换中,

如果给定的转换类型不兼容(转换失败),则会报错,但是 as 转换失败的话,

不会报错,会返回null

如:p1 as Student //把p1转换为Student类型,如果失败返回null


多态:

概念:多态是指两个或多个属于不同类的对象,对于同一个消息(方法调用)

 作出不同响应的方式。

实现多态的方式:

1.重载

2.虚方法

3.抽象方法(还有抽象属性) → 抽象的成员没有主体

4.泛型如:<T>

定义虚方法语法:

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

{

//方法体

//注意:虚方法不能是private

}

定义抽象方法语法:

访问修饰符 abstract 返回类型 方法名(); //没有方法体、不能是privatte

定义抽象属性语法:

public abstract 数据类型 属性名

{

get;set;  //不能带有字段

}

子类中重写虚方法和抽象方法语法:

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

{

//方法体

//注意:子类中重写父类的方法必须要:返回类型、方法名、参数都一样

}

子类中重写抽象属性例子:

public override int Age

{

get{return age;}

set{age = value;}

}

虚方法 和 抽象方法 区别:

虚方法:

1.用virtual修饰

2.要有方法体

3.可以被子类override(重写)

4.除了密封类、静态类外都可以写(虚方法)

抽象方法:

1.用abstract修饰

2.没有方法体

3.必须被非抽象的子类override(重写)

4.必须存在于抽象类中

抽象类:

1.有抽象方法(属性)的类一定是抽象类

2.抽象类不仅可以包含抽象方法、抽象属性,同样也可以包含其他属性、方法和构造函数

3.抽象类不能被实例化

4.抽象类不能是静态或者密封的,因为静态类和密封类都不能被继承

例子:

public abstract class Person //抽象类 Person 为父类

{

//定义了一个抽象方法

public abstract string Test();

}

public class Employee:Person  //继承了Person类

{

//由于Employee类不是抽象类,所以必须重写override父类Person的Test()方法

public override string Test()

{

//方法体

return ""; //override 必须要方法名、参数、返回类型都相同

}

}

记住:抽象类不能被实例化

Person p = new Person(); //这样写会报错

但是,可以这样写:

Person p = new Employee(); //这样写是正确的

那么调用p.Test() 方法 会执行Employee里面的Test()方法,

也就是说,父类的方法一旦被子类重写override以后,那么创建

的父类对象就会去调用它实际类型对象的方法(就是被重写后的方法)

PS:抽象成员必须被非抽象子类override重写

当然,如果是虚方法的话,在子类中没有被重写,那么就会调用父类的方法