面向过程:
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展。
面向对象:
面向对象的三个核心要素是:封装、继承、多态。
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护。
缺点:性能比面向过程低。
面向过程的思维方式,它更加注重这个事情的每一个步骤以及顺序。他比较直接高效,需要做什么可以直接开始干。
面向对象的思维方式,它更加注重事情有哪些参与者,需求里面有哪些对象,这些对象各自需要做些什么事情。将其拆解成一个个模块和对象,这样会更易于维护和拓展。
13.1 继承的含义
1)什么是继承?
继承是在类之间建立一种相交关系,使得新定义的派生类(子类)的实例可以继承已有基类(父类)的特征和能力,而且还可以加入新的特性或者修改已有的特性建立起类的新层次。
注意:object是所有类的基类。
白话:我们可能会在一些类中,写一些重复的成员/方法,我们可以将这些重复的成员/方法,单独地封装到一个类中,作为这些类的父类。
例如:Person是父类(基类)
Student、Teacher、Driver是子类(派生类)
2)继承的语法:
[public] class 子类类名:父类类名
public class Student:Person{ }
3)继承的作用
① 是在一些比较一般的类的基础上构造、建立和扩充新类的最有效的手段
② 简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系。
③ 提供了软件复用功能,如果说类B继承类A,那么只需要在类B中添加类A中没有的类成员即可,这样能减小代码和数据的冗余度,大大的增加了程序的复用性。
④ 继承通过增强一致性来减少模块间的接口和界面,大大增加了程序的易维护性。
4)子类继承了什么
子类继承了父类的属性和方法,但是子类并没有继承父类的私有字段。
子类没有继承父类的构造函数,但是,子类会默认地调用父类的无参数的构造函数,创建父类对象,让子类可以使用父类中的成员。所以,如果在父类中重写了一个有参数的构造函数之后,那个无参数的就被干掉了,子类就调用不到了,所以子类会报错。
解决办法:
① 在父类中重新写一个无参数的构造函数。
② 在子类中显示的调用父类的构造函数,使用关键字:base()。
13.2 继承的特点
1)继承的特点:
① 派生类是对基类的扩展,派生类可以添加新的成员,但不能移除已经继承的成员的定义。
② 继承可以传递。比如说类C继承类B,类B又继承类A,那么类C不但继承了类B声明的成员,同时也继承了类A声明的成员。
③ 构造函数和析构函数不能直接被继承,除此之外其他成员可以直接被继承。基类中成员的访问方式只能决定派生类中能否访问它们。
④ 派生类如果定义了与基类成员名相同的新成员,那么就可以覆盖基类中的成员。但是这并不是删除了这些成员,而是不能访问再它们而已。
new关键字:1.创建对象 2.隐藏从父类那里继承过来的同名成员,隐藏的后果就是子类调用不到父类的成员
⑤ 基类可以定义虚方法、虚属性及虚索引指示器,它的派生类可以重载这些成员,从而展示出它们的多态性。
⑥ 派生类中能从一个类中继承,可以通过接口来实现多重继承。
2)继承的特性:
单根性:一个子类只能有一个父类。
传递性:可以一个传递一个(爷爷传父亲,父亲传儿子)
13.3 继承的练习
//1)创建父类:
public class Person
{
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 char _gender;
public char Gender
{
get { return _gender; }
set { _gender = value; }
}
public Person(string name,int age,char gender)
{
this.Name = name;
this.Age = age;
this.Gender = gender;
}
}
//2)创建Driver子类:
public class Driver:Person
{
private int _driveTime;
public int DriveTime
{
get { return _driveTime; }
set { _driveTime = value; }
}
public void DriverSayHello()
{
Console.WriteLine("我叫{this.Name},我是司机,我年龄是{this.Age},我是{this.Gender}人,我的驾龄是{this.DriveTime}");
}
public Driver(string name,int age,char gender,int driveTime) : base(name, age, gender)
{
this.DriveTime = driveTime;
}
}
//3)创建Programmer子类:
public class Programmer:Person
{
private int _workYear;
public int WorkYear
{
get { return _workYear; }
set { _workYear = value; }
}
public void ProgrammerSayHello()
{
Console.WriteLine("我叫{this.Name},是一个程序员,我年龄是{this.Age},我是{this.Gender}生,我的工作年限是{this.WorkYear}年");
}
public Programmer(string name,int age,char gender,int workYear) : base(name, age, gender)
{
this.WorkYear = workYear;
}
}
//4)创建Reporter子类:
public class Reporter:Person
{
private string _hobby;
public string Hobby
{
get { return _hobby; }
set { _hobby = value; }
}
public void ReporterSayHello()
{
Console.WriteLine("我是{this.Name},我是记者,我的爱好是{this.Hobby},我是{this.Gender}生,我今年{this.Age}岁了");
}
public Reporter(string name,int age,char gender,string hobby) : base(name, age, gender)
{
this.Hobby = hobby;
}
}
//5)在Main函数调取:
static void Main(string[] args)
{
Reporter r = new Reporter("zs", 22, '男',"拍照");
r.ReporterSayHello();
Programmer p = new Programmer("ls", 23, '男',4);
p.ProgrammerSayHello();
Driver d = new Driver("ww", 35, '男',15);
d.DriverSayHello();
Console.ReadKey();
}
输出结果:
我是zs,我是记者,我的爱好是拍照,我是男生,我今年22岁了
我叫ls,是一个程序员,我年龄是23,我是男生,我的工作年限是4年
我叫ww,我是司机,我年龄是35,我是男人,我的驾龄是15
13.3 里氏转换
1)含义:
① 子类可以赋值给父类:如果有一个地方需要一个父类作为参数,我们可以给一个子类代替。
② 如果父类中装的是子类对象,那么可以将这个父类强转为子类对象。
注意:子类对象可以调用父类中的成员,但是父类对象永远都只能调用自己的成员。
例如:
Person p = new Student();
Student ss = (Student)p;
2)is关键词和as关键词:
① is:表示类型转换,如果能够转换成功,则返回一个true,否则返回一个false。
if (p is Student)
{
Student ss = (Student)p;
ss.StudentSayHello();
}
else
{
Console.WriteLine("转换失败");
}
Console.ReadKey();
② as:表示类型转换,如果能够转换则返回对应的对象,否则返回一个null。
Student t = p as Student;
t.StudentSayHello();
Console.ReadKey();
3)里氏转换练习:
class Program
{
static void Main(string[] args)
{
//创建10个对象,通过个循环去调用他们各自打招呼的方法
Person[] pers = new Person[10]; //Person的数组
Random r = new Random(); //随机值
for (int i = 0; i < pers.Length; i++)
{
int rNumber = r.Next(1, 5);
switch (rNumber)//给数组赋值
{
case 1:
pers[i] = new Student();
break;
case 2:
pers[i] = new Teacher();
break;
case 3:
pers[i] = new MeiLv();
break;
case 4:
pers[i] = new Person();
break;
}
}
for (int i = 0; i < pers.Length; i++)
{
if (pers[i] is Student)
{
((Student)pers[i]).StudentSay();
}
else if (pers[i] is Teacher)
{
((Teacher)pers[i]).TeacherSay();
}
else if (pers[i] is MeiLv)
{
((MeiLv)pers[i]).MeiLvSay();
}
else
{
pers[i].PersonSay();
}
}
Console.ReadKey();
}
}
public class Person
{
public void PersonSay()
{
Console.WriteLine("我是人类");
}
}
public class Student : Person
{
public void StudentSay()
{
Console.WriteLine("我是学生");
}
}
public class Teacher : Person
{
public void TeacherSay()
{
Console.WriteLine("我是老师");
}
}
public class MeiLv : Person
{
public void MeiLvSay()
{
Console.WriteLine("我是美女");
}
}
输出结果:
是随机不同角色打招呼的十条语句