其他路径:
CSDN: https://blog.csdn.net/wodehao0808
微信公众号:程序喵星人
更多资源和视频教程,QQ:1902686547
6 面向对象编程基础
6.1 类的概念
1.什么是类?
类是一组具有相同数据结构和相同操作的对象的集合。类是对一系列具有相同性质的对象的抽象,是对对象共同特征的描述。
2.对象和类之间的关系?
对象可以是现实生活中的一个物理对象,还可以是某一类概念实体的实例。例如:一辆汽车、一个人、一本书、乃至一种语言、一个图形、一种管理方式,都可以最为一个对象。
类是一组具有相同数据结构和相同操作的对象的集合。类是对一系列具有相同性质的对象的抽象,是对对象共同特征的描述。比如每一辆汽车是一个对象的话,所有的汽车可以作为一个模板,我们就定义汽车这个类。
可以使用类的定义实例化对象,这表示创建该类的一个实例。
从类定义中产生对象,必须有建立实例的操作。
6.2 类的定义
1.类的定义包括类头和类体两部分,其中类体用一对大花括号{ }括起来,类体用于定义该类的成员。
语法形式:
{
[类成员声明]
}
类成员由两部分组成,一个是类体中以类成员声明形式引入的类成员,另一个则是直接从它的基类继承而来的成员。类成员声明主要包括:常数声明、字段声明、属性声明、事件声明、索引器声明、运算符声明、构造函数声明、析构函数声明、静态构造函数、类型声明等。
2.字段声明
语法形式
[属性集信息] [字段修饰符] 类型 变量声明列表;
其中:
a.变量声明列表--标识符或用逗号 “,” 分隔的多个标识符,并且变量标识符还可用赋值号 “=” 设定初始值。
6.3 Example: 类的概念和定义
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 类的概念和定义
namespace Lesson_24_1
{
class Program
{
static void Main(string[] args)
{
// 对象,实际就是根据类来定义的
Student stu = new Student();
// 给对象变量赋值
stu.strName = "张三";
stu.intNum = 100001;
stu.intAge = 16;
Console.WriteLine( "学生的姓名是:" + stu.strName );
Console.WriteLine( "学生的学号是:" + stu.intNum );
Console.WriteLine( "学生的年龄是:" + stu.intAge );
}
}
// 类头
public class Student // 一般来说 C# 中定义类的时候,它的首字母是大写
{
// 类体
// 定义三个变量,分别用于存储:姓名,学号,年龄
public string strName;
public int intNum;
public int intAge;
}
}
6.4 构造函数
构造函数是类的一种特殊方法,每次创建类的实例都会调用它。
[访问修饰符] 类名()
{
// 构造函数的主体
}
参数化构造函数
[访问修饰符] 类名(参数列表)
{
// 构造函数的主体
}
// 构造函数:用以实例化对象,并且在内存中分配存储数据的区域。
6.5 this关键字
this仅限于在构造函数、类的方法和类的实例中使用。
在类的构造函数中出现的 this 作为一个值类型,它表示正在构造的对象本身的引用。
在类的方法中出现的 this 作为一个值类型,它表示对调用该方法的对象的引用。
在结构的构造函数中出现的 this 作为一个变量类型,它表示对正在构造的结构的引用。
在结构的方法中出现的 this 作为一个变量类型,它表示对调用该方法的结构的引用。
经常在构造函数或者类方法中,如果传入参数和类字段同名,一定需要在类字段前加上 this。
6.6 Example: 类的构造函数 和 this
Student.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lesson_25_1
{
public class Student
{
public string strName;
public int intNum;
public int intAge;
// 在创建一个类的时候,系统会自动给分配一个无参的构造函数
public Student()
{
}
// 有参构造函数
public Student ( string p_strName, int p_intNum, int p_intAge )
{
// this 表示的是访问的是这个对象本身的数据
this.strName = p_strName;
this.intNum = p_intNum;
this.intAge = p_intAge;
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 类的构造函数 和 this
namespace Lesson_25_1
{
class Program
{
static void Main(string[] args)
{
// 根据类的构造函数去实例化一个对象
Student stu = new Student(); // new 就是在内存中分配存储数据区域。
// 根据有参构造函数来实例化对象
Student stu2 = new Student( "张三", 10001, 16 );
Console.WriteLine( "学生的名字:" + stu2.strName );
Console.WriteLine( "学生的学号:" + stu2.intNum );
Console.WriteLine( "学生的年龄:" + stu2.intAge );
}
}
}
6.7 方法
定义:表示定义对象的行为。
声明:
[访问修饰符] [返回类型] <方法名>( [参数列表] )
{
// 方法主体
}
[访问修饰符] 可选,默认情况下为 private。
如果不需要任何返回值,[返回类型]使用void数据。
6.8 方法的调用
语法
对象名.方法名( [参数列表] )
实例 点号 类中的方法
6.9 Example: 方法 和 方法调用
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lesson_26_1
{
class Person
{
// 无参方法
public string say()
{
string strResult = "这是一个说话的方法";
return strResult;
}
// 在方法定义的时候,我们把方法里的参数叫形参
public string doWork( string p_strJob )
{
string str = "我的工作是:" + p_strJob;
return str;
}
// 无返回值方法
public void doWrite()
{
Console.WriteLine( "这是 Person 里面的 doWrite 方法" );
}
}
}
OperatorMethod.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lesson_26_1
{
class OperatorMethod
{
private int _intNumOne;
private int _intNumTwo;
public OperatorMethod( int p_intNumOne, int p_intNumTwo )
{
this._intNumOne = p_intNumOne;
this._intNumTwo = p_intNumTwo;
}
public int Add()
{
return this._intNumOne + this._intNumTwo;
}
public int Div()
{
return this._intNumOne - this._intNumTwo;
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 方法 和 方法调用
namespace Lesson_26_1
{
class Program
{
static void Main(string[] args)
{
Person p = new Person();
Console.WriteLine( p.say() );
// 方法在调用的时候传递的参数叫实参
Console.WriteLine( p.doWork( "程序员" ) );
p.doWrite();
OperatorMethod opm = new OperatorMethod( 10, 20 );
Console.WriteLine( opm.Add() );
Console.WriteLine( opm.Div() );
}
}
}
6.10 方法的参数
C#中方法的参数有 四 种类型:
值参数,不含任何修饰符。
引用型参数,以 ref 修饰符声明。
输出参数,以 out 修饰符声明。
数组型参数,以 params 修饰符声明。
6.10.1 Example: 方法的参数
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lesson_27_1
{
class Person
{
// 参数:值传递
public void changeAge( int p_intAge )
{
p_intAge = p_intAge + 10;
}
// 参数:ref 传递
public void changeAge( ref int p_intAge )
{
p_intAge = p_intAge + 10;
}
// 参数:out 传递
public void modifyAge( out int p_intAge )
{
p_intAge = 23;
}
// params 表示参数是可变的数组
public void showInfo( string p_str, params int[] args )
{
foreach ( int arg in args )
{
Console.WriteLine( "年龄是:" + arg );
}
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 方法的参数
namespace Lesson_27_1
{
class Program
{
static void Main(string[] args)
{
int intAge = 16;
Person p = new Person();
// 值参数传递
p.changeAge( intAge ); // 值参数传递。实际是克隆了一份值,所以在 changeAge 内改变值,不会影响到原有的intAge值
Console.WriteLine( "值传递调用后 intAge = " + intAge ); // 16
// ref引用参数传递
// 使用 Ref 的数据在使用前必须赋值
int intAge2 = 16; // 使用ref 必须赋值
p.changeAge( ref intAge2); // ref 引用传递。实际是直接使用(不克隆),所以在 changeAge 内改变值,会影响到 intAge2 值
Console.WriteLine("ref引用传递调用后 intAge2 = " + intAge2); // 26
// out引用参数传递
// 使用 out 的数据在使用前可以赋值,也可以不赋值
int intAge3 = 16; // 使用 out 可以赋值
int intAge4; // 使用 out 可以不赋值
p.modifyAge( out intAge3 ); // out 引用传递。实际是直接使用(不克隆),所以在 modifyAge 内改变值,会影响到 intAge3 值
Console.WriteLine("out 引用传递调用后 有赋值的 intAge3 = " + intAge3 ); // 23
p.modifyAge( out intAge4 ); // out 引用传递。实际是直接使用(不克隆),所以在 modifyAge 内改变值,会影响到 intAge4 值
Console.WriteLine("out 引用传递调用后 无赋值的 intAge4 = " + intAge4 ); // 23
// params
int[] intArgs = { 12, 13, 14, 15, 16 };
p.showInfo( "", intArgs );
int[] intArgs2 = { 6, 8, 13 };
p.showInfo("", intArgs2);
}
}
}
6.11 静态类和静态方法
类的数据成员可以分:
静态字段;
实例字段;
静态字段是和类相关联的,不依赖特定对象的存在。
实例对象是和对象相关联的,访问实例字段依赖于实例的存在。
含义与用法:
通常若一个方法声明中含有 static 修饰符,则表明这个方法是静态方法。同时说明它只对这个类中的静态成员操作,不可以直接访问实例字段。
若一个方法声明中不包含 static 修饰符,则该方法是一个实例方法。一个实例方法的执行与特定对象关联,所以需要一个对象存在。实例方法可以直接访问静态字段和实例字段。
6.11.1 Example: 静态类 和 静态方法
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lesson_28_1
{
// public 修饰符表示 这个类可以在 本命名空间和其他命名空间 中使用
public class Person
{
// static 表明是一个静态的字段,所谓的静态字段是长期驻留在内存中的。
public static string s_strCountry;
// 方法加上 static 修饰符后,就是一个 静态方法。
public static void changeCountry()
{
Person.s_strCountry = "德国";
}
// 实例字段
public string strName;
public Person( string p_strName )
{
this.strName = p_strName;
}
// 实例方法
public void showInfo()
{
Console.WriteLine( "name = " + this.strName );
Console.WriteLine( "country = " + s_strCountry ); // 实例方法中可以访问 静态字段
}
// 静态方法
public static void showStaticInfo()
{
// Console.WriteLine( "static func name = " + this.strName ); // 静态方法中,无法访问 实例字段
Console.WriteLine( "static func country = " + s_strCountry );
}
}
}
OperatorMethod.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lesson_28_1
{
// 加上 static 后,这个类就是一个静态类,静态类不能实例化对象。
public static class OperatorMethod
{
// public int intResult; // 在静态类中不允许出现 实例字段 和 实例方法。
public static int s_intResult; // 静态字段
public static int Add( int a, int b ) // 静态方法
{
s_intResult = a + b;
return s_intResult;
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 静态类 和 静态方法
namespace Lesson_28_1
{
class Program
{
static void Main(string[] args)
{
Person.s_strCountry = "中国"; // 不需要实例对象,直接使用 类 访问 静态字段;
Console.WriteLine( Person.s_strCountry );
Person.changeCountry(); // 不需要实例对象,直接使用 类 访问 静态方法;
Console.WriteLine( Person.s_strCountry );
Person p = new Person( "张三" ); // 创建一个实例对象
p.showInfo(); // 通过 实例对象 访问 实例方法
Person.showStaticInfo(); // 通过 类 方位 静态方法
}
}
}
6.12 方法的重载
方法重载,必须要求:
1.相同的方法名;
2.相同的返回值类型;
重载方法有两种方式:
1.指定不同个数的参数;
2.指定不同类型的参数;
方法重载跟 形参字段名字 无关;
比如:
a( int i );
a( int m );
两个方法是同一个,形参字段名(i 和 m)不会影响导致方法不一致。
6.13 命名空间的概念
语法:
namespace 命名空间的名称
{
// 该名称空间的所有的类都放在这里
}
6.14 Example: 方法重载 和 命名空间
命名空间:Lesson_29_1
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 方法重载 和 命名空间
namespace Lesson_29_1
{
// public 修饰符,表示类可以在 同一命名空间 和 其他命名空间 中使用。
// internal 修饰符,表示类只能在 同一命名空间 中使用。
public class Person
{
// 方法重载必须要求:方法的名字 和 返回类型 必须一致。
// 充话费的方法
public void chongHuaFei( string str, double d )
{
Console.WriteLine( "给:" + str + "充了:" + d );
}
// 方法重载--参数个数不同
public void chongHuaFei( string str )
{
Console.WriteLine( "充话费" );
}
// 方法重载--参数类型不同
public void chongHuaFei( double d )
{
Console.WriteLine( "充了:" + d );
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 方法重载 和 命名空间
// 命名空间主要用来区分类,比如:有两个 Person 类,分别在不同的命名空间中。
namespace Lesson_29_1
{
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p.chongHuaFei( 12 );
p.chongHuaFei( "张三" );
p.chongHuaFei( "李四", 23 );
}
}
}
命名空间:Test
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
class Person
{
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lesson_29_1;
namespace Test
{
class Program
{
static void Main(string[] args)
{
// 在 Test 命名空间中,也有一个 Person 类
// 现在需要在 这里 使用 Lesson_29_1 命名空间中的 Person 类
// 步骤
// 1.在资源管理器中,选择 Test -> 引用 -> 右键,选择 “添加引用” -> 选择 "项目" -> "Lesson_29_1"
// 2.如本例中,加入:using Lesson_29_1;
// 3.使用: Lesson_29_1.Person p = new Lesson_29_1.Person();
Lesson_29_1.Person p = new Lesson_29_1.Person();
}
}
}