C#教程8:面向对象编程【01】
一、OOP面向对象定义
面向对象编程 (OOP) 是一种编程范式,它使用对象及其交互来设计应用程序和计算机程序。
OOP中有一些基本的编程概念:
- Abstraction 抽象
- Polymorphism 多态
- Encapsulation 封装
- Inheritance 继承
抽象是通过建模适合问题的类来简化复杂的现实。多态性是对不同的数据输入以不同的方式使用运算符或函数的过程。封装对其他对象隐藏了一个类的实现细节。继承是一种使用已经定义的类形成新类的方法。
二、C# 对象
对象是 C# OOP 程序的基本构建块。对象是数据和方法的组合。数据和方法称为对象的成员。在 OOP 程序中,我们创建对象。这些对象通过方法相互通信。每个对象都可以接收消息、发送消息和处理数据。
创建对象有两个步骤。首先,我们定义一个类。类是对象的模板。它是描述类的对象都共享的状态和行为的蓝图。一个类可用于创建许多对象。在运行时从一个类创建的对象称为该特定类的实例。
Program.cs
var b = new Being(); Console.WriteLine(b);class Being {}
在我们的第一个示例中,我们创建了一个简单的对象。
class Being {}
这是一个简单的类定义。模板的主体是空的。它没有任何数据或方法。
var b = new Being();
我们创建了一个存在类的新实例。为此,我们有新的关键字。 b 变量是创建对象的句柄。
Console.WriteLine(b);
我们将对象打印到控制台以获取对象的一些基本描述。打印一个对象是什么意思?当我们打印一个对象时,我们实际上调用了它的 ToString 方法。但是我们还没有定义任何方法。这是因为创建的每个对象都继承自基础对象。它具有一些在所有创建的对象之间共享的基本功能。其中之一是 ToString 方法。
$ dotnet run Being
三 C# 对象的属性
对象属性是捆绑在类实例中的数据。对象属性称为实例变量或成员字段。实例变量是在类中定义的变量,类中的每个对象都有一个单独的副本。
Program.cs
var p1 = new Person(); p1.name = "Jane";var p2 = new Person(); p2.name = "Beky";Console.WriteLine(p1.name); Console.WriteLine(p2.name);class Person {public string name; }
在上面的 C# 代码中,我们有一个带有一个成员字段的 Person 类。
class Person {public string name; }
我们声明一个名称成员字段。 public 关键字指定成员字段可以在类块之外访问。
var p1 = new Person(); p1.name = "Jane";
我们创建一个 Person 类的实例,并将 name 变量设置为“Jane”。我们使用点运算符来访问对象的属性。
var p2 = new Person(); p2.name = "Beky";
我们创建 Person 类的另一个实例。在这里,我们将变量设置为“Beky”。
Console.WriteLine(p1.name); Console.WriteLine(p2.name);
我们将变量的内容打印到控制台。
$ dotnet run Jane Beky
Person 类的每个实例都有一个单独的名称成员字段副本。
四、C# 的方法
方法是定义在类体内的函数。它们用于使用我们对象的属性执行操作。方法为我们的程序带来了模块化。
方法在 OOP 范式的封装概念中是必不可少的。例如,我们的 AccessDatabase 类中可能有一个 Connect 方法。我们不需要知道 Connect 方法是如何连接到数据库的。我们只需要知道它是用来连接数据库的。这对于划分编程职责至关重要,尤其是在大型应用程序中。
对象分组状态和行为,方法代表对象的行为部分。
Program.cs
var c = new Circle(); c.SetRadius(5);Console.WriteLine(c.Area());class Circle {private int radius;public void SetRadius(int radius){this.radius = radius;}public double Area(){return this.radius * this.radius * Math.PI;} }
在代码示例中,我们有一个 Circle 类。我们定义了两种方法。
private int radius;
我们有一个成员字段。它是圆的半径。私有关键字是访问说明符。它告诉变量仅限于外部世界。如果我们想从外部修改这个变量,我们必须使用公开可用的 SetRadius 方法。这样我们就可以保护我们的数据。
public void SetRadius(int radius) {this.radius = radius; }
这是 SetRadius 方法。 this 变量是一个特殊变量,我们使用它来访问方法中的成员字段。 this.radius 是一个实例变量,而 radius 是一个局部变量,仅在 SetRadius 方法内有效。
var c = new Circle(); c.SetRadius(5);
我们创建一个 Circle 类的实例,并通过在圆的对象上调用 SetRadius 方法来设置它的半径。我们使用点运算符来调用该方法。
public double Area() {return this.radius * this.radius * Math.PI; }
Area 方法返回圆的面积。 Math.PI 是一个内置常量。
$ dotnet run 78.5398163397448
五、C# 访问修饰符
访问修饰符设置方法和成员字段的可见性。 C# 有四个基本的访问修饰符:public、protected、private 和 internal。可以从任何地方访问公共成员。受保护的成员只能在类本身以及继承的类和父类中访问。私有成员仅限于包含类型,例如仅在其类或接口内。可以从同一个程序集(exe 或 DLL)中访问内部成员。
还有两种修饰符组合:protected internal 和 private protected。受保护的内部类型或成员可以被声明它的程序集中的任何代码访问,也可以从另一个程序集中的派生类中访问。私有受保护类型或成员只能在其声明程序集中、通过同一类中的代码或从该类派生的类型中访问。
访问修饰符保护数据免受意外修改。它们使程序更加健壮。
Class | Current assembly | Derived types | Derived types in current assembly | Entire program | |
---|---|---|---|---|---|
public | + | + | + | + | + |
protected | + | o | + | + | o |
internal | + | + | o | o | o |
private | + | o | o | o | o |
protected internal | + | + | + | + | o |
private protected | + | o | o | + | o |
上表总结了 C# 访问修饰符(+ 可访问,o 不可访问)。
Program.cs
var p = new Person(); p.name = "Jane";p.SetAge(17);Console.WriteLine($"{p.name} is {p.GetAge()} years old");class Person {public string name;private int age;public int GetAge(){return this.age;}public void SetAge(int age){this.age = age;} }
在上面的程序中,我们有两个成员字段。一个是公开的,另一个是私有的。
public int GetAge() {return this.age; }
如果成员字段是私有的,则访问它的唯一方法是通过方法。如果我们想修改类之外的属性,则必须将方法声明为 public。这是数据保护的一个重要方面。
public void SetAge(int age) {this.age = age; }
SetAge 方法使我们能够从类定义之外更改私有年龄变量。
var p = new Person(); p.name = "Jane";
我们创建一个 Person 类的新实例。因为 name 属性是公开的,所以我们可以直接访问它。但是,不建议这样做。
p.SetAge(17);
SetAge 方法修改年龄成员字段。无法直接访问或修改它,因为它被声明为私有。
Console.WriteLine($"{p.name} is {p.GetAge()} years old");
最后,我们访问这两个成员来构建一个字符串。
$ dotnet run Jane is 17 years old
具有私有访问修饰符的成员字段不会被派生类继承。
Program.cs
var derived = new Derived(); derived.info();class Base {public string name = "Base";protected int id = 5323;private bool isDefined = true; }class Derived : Base {public void info(){Console.WriteLine("This is Derived class");Console.WriteLine("Members inherited");Console.WriteLine(this.name);Console.WriteLine(this.id);// Console.WriteLine(this.isDefined);} }
在前面的程序中,我们有一个继承自基类的派生类。基类具有三个成员字段。所有这些都具有不同的访问修饰符。 isDefined 成员不被继承。私有修饰符可以防止这种情况。
class Derived : Base
派生类继承自基类。要从另一个类继承,我们使用冒号 (:) 运算符。
Console.WriteLine(this.name); Console.WriteLine(this.id); // Console.WriteLine(this.isDefined);
公共和受保护的成员由派生类继承。它们可以被访问。私有成员不会被继承。访问成员字段的行被注释掉。如果我们取消注释该行,代码将无法编译。
$ dotnet run ... warning CS0414: The field 'Base.isDefined' is assigned but its value is never used ... This is Derived class Members inherited Base 5323
六、C# 构造函数
构造函数是一种特殊的方法。创建对象时会自动调用它。构造函数不返回值。构造函数的目的是初始化一个对象的状态。构造函数与类同名。构造函数是方法,所以它们也可以被重载。
构造函数不能被继承。它们按继承顺序调用。如果我们不为类编写任何构造函数,C# 提供了一个隐式默认构造函数。如果我们提供任何类型的构造函数,则不提供默认值。
Program.cs
new Being(); new Being("Tom");class Being {public Being(){Console.WriteLine("Being is created");}public Being(string being){Console.WriteLine($"Being {being} is created");} }
我们有一个存在类。这个类有两个构造函数。第一个不带参数;第二个接受一个参数。
public Being(string being) {Console.WriteLine($"Being {being} is created"); }
此构造函数采用一个字符串参数。
new Being();
创建了一个存在类的实例。这次在对象创建时调用不带参数的构造函数。
$ dotnet run Being is created Being Tom is created
在下一个示例中,我们启动类的数据成员。变量的初始化是构造函数的典型工作。
Program.cs
var name = "Lenka"; var born = new DateTime(1990, 3, 5);var friend = new MyFriend(name, born); friend.Info();class MyFriend {private DateTime born;private string name;public MyFriend(string name, DateTime born){this.name = name;this.born = born;}public void Info(){Console.WriteLine("{0} was born on {1}",this.name, this.born.ToShortDateString());} }
我们有一个带有数据成员和方法的 MyFriend 类。
private DateTime born; private string name;
我们在类定义中有两个私有变量。
public MyFriend(string name, DateTime born) {this.name = name;this.born = born; }
在构造函数中,我们初始化了两个数据成员。 this 变量是用于引用对象变量的处理程序。
var friend = new MyFriend(name, born); friend.Info();
我们创建一个带有两个参数的 MyFriend 对象。然后我们调用对象的 Info 方法。
$ dotnet run Lenka was born on 3/5/1990
七、C# 构造链
构造函数链接是类从构造函数调用另一个构造函数的能力。要从同一类调用另一个构造函数,我们使用 this 关键字。
Program.cs
new Circle(5); new Circle();class Circle {public Circle(int radius){Console.WriteLine($"Circle, r={radius} is created");}public Circle() : this(1) { } }
我们有一个 Circle 课程。该类有两个构造函数。一个带一个参数,一个不带任何参数。
public Circle(int radius) {Console.WriteLine("Circle, r={0} is created", radius); }
这个构造函数接受一个参数——半径。
public Circle() : this(1) { }
这是没有参数的构造函数。它只是调用另一个构造函数并给它一个默认的半径 1。
$ dotnet run Circle, r=5 is created Circle, r=1 is created
八、C# ToString 方法
每个对象都有一个 ToString 方法。它返回对象的人类可读表示。默认实现返回对象类型的完全限定名称。请注意,当我们使用对象作为参数调用 Console.WriteLine 方法时,会调用 ToString。
Program.cs
var b = new Being(); var o = new Object();Console.WriteLine(o.ToString()); Console.WriteLine(b.ToString()); Console.WriteLine(b);class Being {public override string ToString(){return "This is Being class";} }
我们有一个存在类,我们在其中覆盖了 ToString 方法的默认实现。
public override string ToString() {return "This is Being class"; }
创建的每个类都继承自基础对象。 ToString 方法属于该对象类。我们使用覆盖关键字来通知我们正在覆盖一个方法。
var b = new Being(); var o = new Object();
我们创建一个自定义对象和一个内置对象。
Console.WriteLine(o.ToString()); Console.WriteLine(b.ToString());
我们在这两个对象上调用 ToString 方法。
Console.WriteLine(b);
正如我们之前指定的,将对象作为参数放置到 Console.WriteLine 将调用其 ToString 方法。这一次,我们隐式调用了该方法。
$ dotnet run System.Object This is Being class This is Being class
九、C#对象初始化
对象初始化器让我们在创建时为对象的任何可访问字段或属性分配值,而无需调用构造函数。属性或字段在 {} 括号内分配。此外,我们可以为构造函数指定参数或省略参数。
Program.cs
var u = new User { Name = "John Doe", Occupation = "gardener" }; Console.WriteLine(u);class User {public User() {}public string Name { set; get; }public string Occupation { set; get; }public override string ToString(){return $"{Name} is a {Occupation}";} }
在示例中,我们使用对象初始化器语法创建一个新用户。
public User() {}
我们定义了一个空的构造函数。
public string Name { set; get; } public string Occupation { set; get; }
我们有两个属性:姓名和职业。
var u = new User { Name = "John Doe", Occupation = "gardener" };
我们将值分配给 {} 括号中的属性。
$ dotnet run John Doe is a gardener
C#教程8:面向对象编程【01】相关推荐
- Java基础教程:面向对象编程[2]
Java基础教程:面向对象编程[2] 内容大纲 访问修饰符 四种访问修饰符 Java中,可以使用访问控制符来保护对类.变量.方法和构造方法的访问.Java 支持 4 种不同的访问权限. default ...
- python基础系列教程——python面向对象编程全解
全栈工程师开发手册 (作者:栾鹏) python教程全解 python面向对象编程全解. 面向对象技术简介 一个类占有一个独立的空间,类中的属性叫做类变量,类中的函数,叫做类的方法. 类(Class) ...
- JavaScript 进阶教程(1)--面向对象编程
目录 1 学习目标 2 面向对象介绍 2.1 什么是对象 2.2 什么是面向对象 2.3 JavaScript 中面向对象的基本体现 3 JavaScript 如何创建对象 3.1 字面量方式 3.2 ...
- JavaScript强化教程-JS面向对象编程
对事物的抽象描述 描述这类事物的特征和行为 对象是类的实例 代码实现:创建一个类 function peple(){this.hp=0;this.act = 30;this.name = &q ...
- 下面属于javascript内部对象的有_【JavaScript 教程】面向对象编程——this 关键字...
作者 | 阮一峰 1.涵义 this关键字是一个非常重要的语法点.毫不夸张地说,不理解它的含义,大部分开发任务都无法完成. 前一章已经提到,this可以用在构造函数之中,表示实例对象.除此之外,thi ...
- JavaScript教程-38-JavaScript面向对象编程
1:JavaScript不是面向对象的一种编程语言,而是基于对象的.因为JavaScript是基于对象的一种脚本语言,所以没有所谓的类似java中 类 class 的概念.但是我们可以通过JavaSc ...
- 笔记本电脑java版下载教程_Java面向对象编程笔记本 PDF 下载
主要内容: Ⅰ.语法基础 //导入 java.util 包下的 bai Scanner 类,导入后才能使用它.(放在 public class 之前) //Scanner 类的对象的定义形式 //从键 ...
- java泡泡堂教程_JAVA面向对象编程课程设计——泡泡堂(个人博客)
二.个人负责模块或任务说明 GUI设计 游戏界面类.地图类的实现(实现与Player类的交互) 阿里巴巴扫描纠错 团队博客编写 三.自己的代码提交记录 四.自己负责模块或任务详细说明 1.地图Fiel ...
- Python基础-面向对象编程
本文完全转载自廖雪峰大神的教程: 面向对象编程 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数 ...
- php面向对象项目,PHP的面向对象编程:开发大型PHP项目的方法(一)
PHP(PHP培训 php教程 )的面向对象编程:开发大型PHP项目的方法(一) 作者:Luis Argerich 译者:limodou 这篇文章介绍了在PHP中的面向对象编程(OOP,Object ...
最新文章
- 波士顿动力的机器人会开门了,中国还要奋力追赶
- 51nod 1275 连续子段的差异
- cmd看excel有多少个子表_快看!杭州各区5月房价表出炉!现在买套房要多少钱?...
- 烂泥:CentOS6.5挂载windows共享文件夹
- mysql select 缓存_mysql select缓存机制使用详解
- 首次公开!菜鸟弹性调度系统的架构设计
- 人声处理_10款免费的人声处理工具
- C# 选择按钮 数字排序 找最大值最小值
- 英语------------单词复数形式的规律
- MySQL中union和order by一起使用的方法
- bug[应该已经修复了]:红色方框随机丢失(简书安卓2.0beta)
- CSS3 Transform 变形
- 为什么蓝牙一主多从能解决集中式水表抄表难题?
- 料酒调味不宜用白酒代替
- 大厂Java面试过程中如何介绍自己的项目经历?
- 使用Python将Word表格嵌入Excel中!
- elastic APM 深入测试 一 (无嵌套调用的分布式微服务监控)
- 计算机信息管理 日语,2017年北京科技大学高职计算机信息管理(第一外语:日语)...
- 从零开始带你称为MySQL实战优化高手(儒猿技术窝)
- 核函数和核矩阵【转】
热门文章
- 概率统计笔记:高斯威沙特分布
- pytorch 笔记: torch.nn.Embedding
- 【数据可视化应用】华夫饼型柱状图(附R语言代码)
- Java实战应用50篇(一)-Java并发编程:volatile关键字解析
- tableau可视化数据分析60讲(二十一)-tableau预测及趋势线
- 深度学习核心技术精讲100篇(十一)-Google利器超强特征提取网络(Transformer)
- 如何让签到成为提升用户活跃度的利器
- matlab破损皮革定位,皮革下料
- TensorFlow2简单入门-图像加载及预处理
- LeetCode-剑指 Offer 14- I. 剪绳子