面向对象编程,类,实例介绍

我被代码海扁 @codebeatme-s @103466775
阅读 10:02·字数 3012·发布 

面向对象编程

面向对象编程,不是简单的定义变量和函数,而是一套更为复杂的代码组织方案,他倾向于以贴近现实或需求的某个事物为单位,完成其相关数据的存储和功能的实现。比如,在人事管理系统中,你可以把员工视为一个单位,并编写姓名,年龄,考核功能的代码。

虽然不需要全部,但支持面向对象编程的语言,应该具有以下的某些特点。

封装
封装是指对象可以隐藏其包含的数据和功能,仅公开特定的部分。外部仅能通过此部分来访问对象中的数据和使用对象中的功能。比如,员工拥有工资等级,但外部不能直接修改,只能通过员工的考核功能来重新评估他。
继承
继承是指通过某种方式,一个对象可以以另一个对象为基础,拓展新的数据和功能。比如,管理者从员工继承,拓展了新的管理规划功能。
多态
多态是指在继承中,对于同一功能,对象可以拥有不同的实现。比如,同样是考核功能,管理者考核的实现与员工不同。

为何使用面向对象编程?
试想仅采用变量和函数来完成一个超级复杂的项目,我们可能会拥有复杂的数组,以及参数众多的函数,这加大了维护的难度。面向对象编程缓解了这些情况,复杂的问题被分散在封装,继承,多态等特点中。

类是对象的设计蓝图,是对象的类型,他描述了对象包含哪些数据和功能。实例化后的类就是对象,对象也被称为类的实例。当然,“实例”一词并不局限于类,他也适用于接口,结构等其他概念。

类的成员

类的成员用于表述具体的数据和功能,从形式上可以划分为以下几类,当然,某些语言可能会支持更多。

字段/变量
类的字段用于存储数据,在一些语言中,他也被称为变量。
方法/过程
类的方法用于完成某种运算,你可以将其视为类所拥有的函数,在一些语言中,他也被称为过程。
属性
类的属性可用于限制或检验字段的访问,对外部来说,属性的用法与字段类似,但实际上属性是一种语法糖,其本质是方法。
构造器/构造函数
类的构造器也被称为构造函数,他给予了在创建对象时进行初始设置的机会,你可以使用其提供的参数来初始化字段或属性。构造器的名称不能随意指定,一般采用类名或某种特定名称,比如,Newconstructor等。

如果依据成员的归属,那么类的成员可以分为两大类。

实例成员
实例成员需要通过实例才能访问,虽然出现在类的定义中,但通过类是无法直接使用他们的。这种运作方式可以让每个实例拥有各自独立的数据,就像每位员工都应该拥有自己的姓名一样。
类成员/静态成员/共享成员
与实例成员不同,类成员可以通过类直接访问,类成员也被称为静态成员或共享成员。

如果依据读写规则,类的某些成员可以细分为三种。

可读写成员
可读写成员允许读取和写入,对于属性来说,需要拥有getset访问器。
只读成员
只读成员只允许读取,对于属性来说,只能拥有get访问器,对于字段则需要拥有特定关键字,比如readonly
只写成员
只写成员只允许写入,对于属性来说,只能拥有set访问器。

下面展示了 C# 类Employee,他包含了实例字段namelevel,类字段Count,实例属性Name,实例方法Evaluate,以及一个构造器。

classes.cs
// 关于员工的类 Employee
class Employee
{
	// 类字段 Count,记录创建过的 Employee 实例的个数
	public static int Count;
	// 字段 name,表示员工姓名
	string name;
	// 字段 level,表示员工工资等级
	protected int level;

// 属性 Name,用于控制字段 name 的访问 public string Name { get { return name; } set { // 员工姓名不接受没有意义的字符串 if (string.IsNullOrEmpty(name)) return;
name = value; Console.WriteLine($"员工改名为:{name}"); } }

// 方法 Evaluate,根据工作量评估员工的工资等级 public void Evaluate(int workload) { level = workload / 365; Console.WriteLine($"员工 {Name} 的工资等级为:{level}"); }
// 构造器,用于初始化员工 public Employee(string n) { // 由于类字段 Count 归属于类而非某个实例,因此会一直累计 // 创建过的 Employee 实例的个数加 1 Count++; // 初始化员工姓名 name = n; } }

类的成员访问级别

类的成员访问级别用于控制成员的可访问性,一般分为私有,保护,公共三种,其具体效果可能因语言的不同而不同。

私有
访问级别为私有的成员,只能在定义他的类或其实例中被访问。
保护
访问级别为保护的成员,在私有访问级别的基础上,还可以被派生类或其实例访问。关于派生类,会在稍后给出说明。
公共
访问级别为公共的成员,可以在任何位置被访问。

对于之前例子中定义的Employee类,成员CountName,Evaluate以及构造器的访问级别为公共,因此可在任意位置访问。

*.cs
// 实例化类 Employee
Employee employee1 = new("小熊猫");
// 通过属性修改员工姓名
employee1.Name = "浣熊";
// 使用年工作量 12345 评估员工
employee1.Evaluate(12345);
// 显示创建过的 Employee 实例的个数
Console.WriteLine($"创建了 {Employee.Count} 个 Employee");

// 再次实例化类 Employee Employee employee2 = new("大熊猫"); // 此时显示的个数为 2 Console.WriteLine($"创建了 {Employee.Count} 个 Employee");
员工改名为:浣熊
员工 浣熊 的工资等级为:33
创建了 1 个 Employee
创建了 2 个 Employee

类的继承

一个类可以继承自另一个类,这实现了面向对象编程的继承性,被继承的类被称为基类,父类或超类,而继承自基类的类,被称为派生类或子类。派生类拥有基类已定义的成员,并可在此基础上添加自己的新成员。

派生类Manager继承自Employee,虽然不能访问Employee的私有成员name,但他定义了一个新的公共方法Manage,并访问了Employee的非私有成员Namelevel

classes.cs
// 关于管理者的类 Manager
class Manager : Employee
{
	// Manager 类加入了新的方法 Manage
	public void Manage()
	{
		// 访问基类的非私有成员
		Console.WriteLine($"{Name} 来管理自己了,哦,看下工资等级?{level}");
	}

// 构造器,用于初始化管理者 public Manager(string n) : base(n) { } }
*.cs
// 实例化类 Manager
Manager manager = new("老熊猫");
// 调用 Manager 类定义的 Manage 方法
manager.Manage();
老熊猫 来管理自己了,哦,看下工资等级?0

什么是类的多级继承?
多级继承(Multilevel Inheritance)也被称为多层继承,是指某个派生类成为另一个类的基类的行为。比如,类B是类A的派生类,同时还是类C的基类。

什么是类的多重继承?
多重继承(Multiple Inheritance)是指一个类从多个基类继承的行为,这种行为会产生多义性问题,即同一个基类被同一个派生类多次继承,导致派生类无法确定使用他们中的哪一个,在访问该基类成员的时候。需要指出,并非所有的语言都支持多重继承。

什么是类的虚继承?
类的虚继承主要用于解决多重继承带来的多义性问题,当一些类采用虚继承后,从这些类多重继承的派生类,将只拥有一份虚基类的成员。这里的虚基类是指被虚继承的基类。

在下面的 C++ 代码中,类C多重继承自类B1B2,因此类C两次继承了类A,在调用基类AShow方法时,将无法确定是选择来自于B1A,还是B2A

classes.cpp
#include <iostream>

// 基类 A,拥有 Show 方法 class A { public: void Show() { std::cout << "A::Show" << std::endl; } };
// 派生类 B1,B2 均继承自 A class B1 : public A { }; class B2 : public A { };
// 派生类 C,将继承 A 两次 class C : public B1, public B2 { };
// 创建实例,并调用 Show 方法 int main() { C c; // ERROR 无法确定调用哪个 A 的 Show 方法 c.Show(); }

调整代码,将类B1B2改为虚继承后,对方法Show的调用不再有问题。

classes.cpp
// 改为采用虚继承的方式
class B1 : virtual public A
{
};
class B2 : virtual public A
{
};
A::Show

类的多态

类的多态主要体现在本质是方法的成员上,当然,这包括方法本身,多态的应用体现了不同对象对功能差异化的需求。

内容分类

源码

classes.cs·codebeatme/programming·GitHub
classes.cpp·codebeatme/programming·GitHub