<5> 面向对象到底有什么(中)?
2018-01-11 14:03
267 查看
在<3> 面向对象到底有社么(上)一文中,我们说了下关于面向对象和面向过程的区别和优劣性。在面向对象里边,也谈了下关于“面向对象三大特性”的其中一个特性“封装性”的简单理解。在这一文中,我们主要一起来了解下关于面向对象的第二个特性“继承”的理解,一起来看下“继承”到底是什么?继承到底有什么作用?以及“继承”在什么情况下会用到?继承的优点在哪里?
2.2 ”继承“到底是什么?为什么要有它这个东西?
我是觉得,现在的名称翻译还是挺符合“顾名思义”的原则的,继承在我们一般人的眼里,就代表了“依法拿到遗产”、“把前人的文化、知识传承过来”等意思,在高级程序设计语言这里,其实也有类似的意味。
还是接着我们上一篇文章的“Person”类作为例子,接着说。实际上,在我们的项目中,“人”只是一个比较宽泛的“类别”,在这个社会群体中,“学生”,“老师”,“校长”等等社会职业属于“人”这个类型,但是这些社会职业本身也都是单独的“类别”。假设:我们在“Person”类里边添加关于“学生”,“老师”,“校长”的一些信息,结果会是这样的:
如果我们在某个地方只用学生这个“类别”,我们就不得不来一次“Person student(25,'男',“who”)“一次,但是我们发现,在创建一个对象并初始化的时候,类已经为我们创建好了”老师“,”校长“等社会角色身上存在的一些特性(老师教授的”课“有哪些,校长管理的是”哪个学校“等等)。而我们明白的是,学生并不需要知道具备这些特性,因为他们只需要做好自己,了解自己的特性就好。由于我们把这些内容都融合在一个类里边,所以每次在创建对象的时候,就会有多余的数据被创建,比如:std::vector<std::string>
_lesson、std::string _school等等,造成代码冗余,工程文件过大,不易管理、可读性不高。当然,我们也可以这么来写设计类:
看见上边的内容,可以发现每个一共有四个类,每个类中都有相同的内容:年龄、性别、姓名、获取年龄、获取性别、获取姓名,如果以后需要添加内容,也许会有数十个甚至上百个成员函数或者成员变量是相同的。会导致代码的复用性不高,过于冗余,不够精简。因此,这个时候,我们可以用上我们的面向对象的第二个特性”继承“了。
2.3 ”继承“该怎么用?
我们依然是以”Person“类为原型来设计”学生“、”老师“、”校长“等社会角色。在这里使用了”继承“的相关内容:
这样看起来,不管是Student、Teacher、还是Principal类,都具备了Person的属性,同时也拥有了自己的特性,展现了三个不同人群之间的差异,但是同时,这种“is-a”的关系,也是继承的一个重要关系,即:派生类也是一个基类。并且在使用类的时候,按需使用。对于功能的扩展好,都比较明晰,减少了冗余代码,增加了可读性,这些也是“继承”能够被支持的重要原因之一。
未完,待续。
2.2 ”继承“到底是什么?为什么要有它这个东西?
我是觉得,现在的名称翻译还是挺符合“顾名思义”的原则的,继承在我们一般人的眼里,就代表了“依法拿到遗产”、“把前人的文化、知识传承过来”等意思,在高级程序设计语言这里,其实也有类似的意味。
还是接着我们上一篇文章的“Person”类作为例子,接着说。实际上,在我们的项目中,“人”只是一个比较宽泛的“类别”,在这个社会群体中,“学生”,“老师”,“校长”等等社会职业属于“人”这个类型,但是这些社会职业本身也都是单独的“类别”。假设:我们在“Person”类里边添加关于“学生”,“老师”,“校长”的一些信息,结果会是这样的:
//---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- // 类的封装 class Person{ public: Person(int age, char gender, std::string name) :_age(age), _gender(gender), _name(name) { _score = new double[10]; } ~Person(); public: int _age; char _gender; std::string _name; // 学生 double *_score; std::string _studentID; std::string _major; // 老师 std::vector<std::string> _lesson; std::string _teacherID; // 校长 std::string _school; //··· //··· //··· public: const int get_age() { return _age; } const char get_gender() { return _gender; } const std::string get_name() { return _name; } void set_age(const int &value); void set_gender(const char &value); void set_name(const std::string &value); }; void Person::set_age(const int &value){ this->_age = value; } void Person::set_gender(const char &value) { this->_gender = value; } void Person::set_name(const std::string &value) { this->_name = value; } Person::~ 4000 Person() { // } int main() { // 声明一个Person类型的对象 // 请注意:对象的概念在这里开始出现,因为Person是一个集合,一个类型,那么类型的一个一个实际的例子,就是对象 Person m_person(25, '男', "chengzhen"); // 获得年龄 m_person.get_age(); // 获得性别 m_person.get_gender(); // 获得姓名 m_person.get_name(); // 设置年龄 m_person.set_age(30); // 设置性别 m_person.set_gender('nv'); // 设置姓名 m_person.set_name("Charmain"); std::cin.get(); }
如果我们在某个地方只用学生这个“类别”,我们就不得不来一次“Person student(25,'男',“who”)“一次,但是我们发现,在创建一个对象并初始化的时候,类已经为我们创建好了”老师“,”校长“等社会角色身上存在的一些特性(老师教授的”课“有哪些,校长管理的是”哪个学校“等等)。而我们明白的是,学生并不需要知道具备这些特性,因为他们只需要做好自己,了解自己的特性就好。由于我们把这些内容都融合在一个类里边,所以每次在创建对象的时候,就会有多余的数据被创建,比如:std::vector<std::string>
_lesson、std::string _school等等,造成代码冗余,工程文件过大,不易管理、可读性不高。当然,我们也可以这么来写设计类:
//---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- // 类的封装 class Person{ public: Person(int age, char gender, std::string name) :_age(age), _gender(gender), _name(name) {} ~Person(); public: int _age; char _gender; std::string _name; public: const int get_age() { return _age; } const char get_gender() { return _gender; } const std::string get_name() { return _name; } void set_age(const int &value); void set_gender(const char &value); void set_name(const std::string &value); }; //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- // 类的封装 class Student { public: Student(int age, char gender, std::string name) :_age(age), _gender(gender), _name(name) { _score = new double[10]; } ~Student(); public: int _age; char _gender; std::string _name; // 学生 double *_score; std::string _studentID; std::string _major; public: const int get_age() { return _age; } const char get_gender() { return _gender; } const std::string get_name() { return _name; } void set_age(const int &value); void set_gender(const char &value); void set_name(const std::string &value); }; //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- // 类的封装 class Teacher { public: Teacher(int age, char gender, std::string name) :_age(age), _gender(gender), _name(name) {} ~Teacher(); public: int _age; char _gender; std::string _name; // 老师 std::vector<std::string> _lesson; std::string _teacherID; public: const int get_age() { return _age; } const char get_gender() { return _gender; } const std::string get_name() { return _name; } void set_age(const int &value); void set_gender(const char &value); void set_name(const std::string &value); }; //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- // 类的封装 class Principal { public: Principal(int age, char gender, std::string name) :_age(age), _gender(gender), _name(name) {} ~Principal(); public: int _age; char _gender; std::string _name; // 校长 std::string _school; //··· //··· //··· public: const int get_age() { return _age; } const char get_gender() { return _gender; } const std::string get_name() { return _name; } void set_age(const int &value); void set_gender(const char &value); void set_name(const std::string &value); };
看见上边的内容,可以发现每个一共有四个类,每个类中都有相同的内容:年龄、性别、姓名、获取年龄、获取性别、获取姓名,如果以后需要添加内容,也许会有数十个甚至上百个成员函数或者成员变量是相同的。会导致代码的复用性不高,过于冗余,不够精简。因此,这个时候,我们可以用上我们的面向对象的第二个特性”继承“了。
2.3 ”继承“该怎么用?
我们依然是以”Person“类为原型来设计”学生“、”老师“、”校长“等社会角色。在这里使用了”继承“的相关内容:
#include <iostream> #include <vector> #include <cmath> #include <string> //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- // Person ( 基类 ) class Person { public: Person(int age, char gender, std::string name) :_age(age), _gender(gender), _name(name) {} ~Person(); public: int _age; char _gender; std::string _name; public: const int get_age() { return _age; } const char get_gender() { return _gender; } const std::string get_name() { return _name; } void set_age(const int &value); void set_gender(const char &value); void set_name(const std::string &value); }; void Person::set_age(const int &value) { this->_age = value; } void Person::set_gender(const char &value) { this->_gender = value; } void Person::set_name(const std::string &value) { this->_name = value; } Person::~Person() { // } //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- // Student ( 派生类,继承自Person ) class Student :public Person { public: Student(int age, char gender, std::string name, double *score,std::string ID, std::string major) : Person(age,gender,name), _score(score), _studentID(ID), _major(major) {} ~Student(){} private: double *_score; std::string _studentID; std::string _major; public: const double* get_score() { return _score; } const std::string get_id() { return _studentID; } const std::string get_major() { return _major; } void set_score(const double* score) { std::memcpy(_score, score, sizeof(score) / sizeof(score[0])); } void set_id(const std::string& id) { _studentID = id; } void set_major(const std::string& major) { _major = major; } }; //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- // Teacher ( 派生类,继承自Person ) class Teacher :public Person { public: Teacher(int age, char gender, std::string name, std::vector<std::string> lesson, std::string id) : Person(age, gender, name), _lesson(lesson), _teacherID(id) {} ~Teacher() {} private: std::vector<std::string> _lesson; std::string _teacherID; public: const std::vector<std::string> get_lesson() { return _lesson; } const std::string get_id() { return _teacherID; } void set_lesson(const std::vector<std::string> lesson) { _lesson.assign(lesson.begin(), lesson.end()); } void set_id(const std::string& id) { _teacherID = id; } }; //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- // Principal ( 派生类,继承自Person ) class Principal :public Person { public: Principal(int age, char gender, std::string name, std::string school) : Person(age, gender, name), _school(school) {} ~Principal() {} private: std::string _school; public: const std::string get_school() { return _school; } void set_school(const std::string& school) { _school = school; } }; int main() { // 声明一个Person类型的对象 // 请注意:对象的概念在这里开始出现,因为Person是一个集合,一个类型,那么类型的一个一个实际的例子,就是对象 Person m_person(25, '男', "chengzhen"); // 获得年龄 m_person.get_age(); // 获得性别 m_person.get_gender(); // 获得姓名 m_person.get_name(); // 设置年龄 m_person.set_age(30); // 设置性别 m_person.set_gender('nv'); // 设置姓名 m_person.set_name("Charmain"); std::cin.get(); }
这样看起来,不管是Student、Teacher、还是Principal类,都具备了Person的属性,同时也拥有了自己的特性,展现了三个不同人群之间的差异,但是同时,这种“is-a”的关系,也是继承的一个重要关系,即:派生类也是一个基类。并且在使用类的时候,按需使用。对于功能的扩展好,都比较明晰,减少了冗余代码,增加了可读性,这些也是“继承”能够被支持的重要原因之一。
未完,待续。
相关文章推荐
- <4> 面向对象到底有什么(上)?
- <6> 面向对象到底有什么(下)?
- 黑马程序员<java基础<面向对象基础知识点>>
- 黑马程序员-----学习日记<5>----面向对象总结1
- Spring MVC 教程,快速入门,深入分析――<mvc:annotation-driven /> 到底做了什么工作
- 面向过程、基于对象、面向对象,到底有什么区别?
- 面向对象系统设计与分析专题<5>__用例模型
- 面向对象,到底玩的是什么
- <<设计模式-可复用面向对象软件的基础>>读书笔记
- < 笔记 > Python - 08 Python 面向对象高级编程(OOP Advanced Features)
- 面向过程、基于对象、面向对象,到底有什么区别?
- 将任意一个jQuery对象进行表单序列化,免除了提交请求时大量拼写表单数据的烦恼,支持键值对<name&value>格式和JSON格式。
- <input type = "submit"> 提交方式和用js的form.submit()有什么区别?
- 小感想 | 面向对象和非面向对象程序的区别是什么?
- 计算机--什么是对象,为什么要面向对象,怎么才能面向对象?
- OC学习--<猜拳游戏> 之 通过面向对象思想实现
- <Professional ASP.NET MVC 5> - Note 01