我爸骑着摩托车,后面坐着我妈,我妈抱着我。
走在一个小路上时,前面突然闯出来一个货车,眼看就要撞上了,我爸突然喊了句
“快把孩子丢出去”
我妈当机立断把我丢到路旁的泥潭。
结果,摩托刹住了,货车也刹住了
我满脸泥巴懵逼的看着他们
========================手动分割线==========================
练习:定义一个矩形类(Rectangle),
成员变量:width,height,
XYPoint类型的point(原始点),
XYPoint类型的center(中心点)。
方法:封装变量为属性,构造方法初始化成员变量width,height,
计算周长、计算面积(ref/out参数修饰)*/
//点是一个结构体类型
public struct XYPoint
{
public double x;
public double y;
public XYPoint(double a, double b)
{
x = a;
y = b;
}
}
//定义一个矩形类,里面有四个字段和四个属性
public class Rectangle
{
private double width;
private double height;
private XYPoint originalPoint;
private XYPoint centerPoint;
//带有参数的构造函数对字段进行初始化
public Rectangle(double w, double h, XYPoint o, XYPoint c)
{
width = w;
height = h;
originalPoint = o;
centerPoint = c;
}
public double Width
{
get { return width; }
set { width = value; }
}
public double Height
{
get { return height; }
set { height = value; }
}
public XYPoint OriginalPoint
{
get { return originalPoint; }
set { originalPoint = value; }
}
public XYPoint CenterPoint
{
get { return centerPoint; }
set { centerPoint = value; }
}
//周长
public void Perimeter()
{
double peri = (this.Height + this.Width) * 2;
Console.WriteLine("矩形的周长是:{0}", peri);
}
//面积
public void Square()
{
double squ = this.Width * this.Height;
Console.WriteLine("矩形的面积是:{0}", squ);
}
}
- 在Main方法中添加如下:
XYPoint a = new XYPoint(4, 5);
XYPoint b = new XYPoint(5, 6);
Rectangle rec = new Rectangle(23, 34, a, b);
rec.Perimeter();
rec.Square();
一、构造方法和析构方法
1.1构造方法 -- 负责开辟内存空间,初始化对象
1.构造方法的方法名必须和类名一致
2.构造方法没有返回值,不需要写void
3.构造方法能够添加参数
4.构造方法允许重载
5.如果没有给类添加构造方法,系统会提供一个默认的构造,也就是只开辟空间
6.如果将某个构造方法设为私有的,就不允许再通过这个构造创建对象
using System;
//面向对象
namespace LessonPrepare09
{
class Student
{
// 字段
public string name;
public int age;
public Student()
{
// 默认的构造方法,只开辟空间
Console.WriteLine("这是默认的构造方法");
}
// 重载构造方法,给方法添加参数,在初始化的同时完成赋值操作
public Student(string _name)
{
name = _name;
}
private Student(int _age)
{
age = _age;
}
public Student(string _name, int _age)
{
name = _name;
age = _age;
Console.WriteLine("这是带参数的构造方法");
}
1.2析构方法 -- 在对象销毁时调用,用于释放内存
1.每个类只能有一个析构方法
2.析构方法不能有返回值
3.析构方法不能有访问权限修饰符
4.析构方法不能带有参数,更不能重载
5.析构方法只能由系统自动调用,不能手动调用
~Student()
{
Console.WriteLine("执行了析构方法");
}
}
练习1:创建一个教师类,特征:姓名、性别、教课内容,内建构造方法初始化所有特征。
class Teacher
{
public string name;
public string gender;
public string className;
public Teacher(string _name, string _gender, string _className)
{
name = _name;
gender = _gender;
className = _className;
}
~Teacher()
{ }
}
练习2:创建一个学生类,特征:学号,姓名,当前授课老师,内建构造方法初始化所有特征。
class Student
{
public string name;
public int number;
public Teacher tea;
public Stu(string _name, int _number, Teacher _tea)
{
name = _name;
number = _number;
tea = _tea;
}
~Stu()
{ }
}
在Main方法中添加如下代码
// 使用默认的构造方法初始化一个对象
Student stu1 = new Student();
// 单独为各个字段赋值
stu1.name = "老王";
stu1.age = 18;
Console.WriteLine("我是{0}, 今年{1}岁", stu1.name, stu1.age);
// 使用带参数的构造方法初始化一个对象,此时不需要单独为字段赋值
Student stu2 = new Student("老汉", 40);
Console.WriteLine("我是{0}, 今年{1}岁", stu2.name, stu2.age);
//这样会报错
// Student stu3 = new Student (10);
// Console.WriteLine (stu3.age);
二、面向对象
面向过程:以事件为中心,关注的是完成事件的详细步骤,一步一步该怎么实现.
面向对象:以事物为中心,关注的是每个事物具备的特征和行为,而完成该事件只是事物所有功能的几个小功能而已.
面向对象的两个核心概念:
类:具备相同特征和行为的事物的抽象,就是一个数据类型.是抽象的概念
对象:类的实例,类的具体表现,生活中的万物都是对象,相当于变量,占用内存空间面向对象的优点:重用性、灵活性和扩展性
面向对象的三大特性:封装、继承、多态
OO:面向对象
OOP:面向对象编程
OPP:面向过程编程
三、面向对象的特性
3.1 封装
封装是面向对象的第一步
封装就是将数据、方法等集合在一个个单元中,我们称之为类
封装的意义在于保护代码、护具,屏蔽复杂性
// 定义一个Person类
class Person
{
/**
*/
// 添加一个私有的字段
string name;
// 为外界提供访问私有字段的接口
public void SetName(string _name)
{
Console.WriteLine("Person类的方法");
name = _name;
}
public string GetName()
{
Console.WriteLine("Person类的方法");
return name;
}
}
注释掉之前定义的Student类
3.2 继承
- 继承的优势:就是省代码,增强程序的可扩展性、可修改性和可复用性.
- 继承的上层:基类,继承的下层:派生类.
- 如果创建类时没有指定基类,默认都是继承自Object(根类)
- 继承具有传递性.C继承自B,B继承自A,则C拥有A与B的全部内容.
- C# 只支持单继承,即派生类只能有一个直接基类
- 派生类获得基类的所有方法、字段、属性和事件
- 派生类可以赋值给基类,但是基类不能赋值给派生类
- 使用场景:当多个类都具有多个相同的字段和方法时,可以将公共部分定义成父类,供其他类去继承
- 通过在派生的类名后面追加冒号和基类名称,可以指定基类
// 定义一个学生类,继承自Person类
class Student : Person // 表示Student类继承自Person类
{
// 为派生类添加自己的字段和方法
private int number;
// 学号
public int Number
{
set
{
Console.WriteLine("Student类的方法");
number = value;
}
get
{
Console.WriteLine("Student类的方法");
return number;
}
}
}
在Main方法中添加如下代码
// 在Student类中不添加任何代码,就可以具有父类的方法
Student stu = new Student();
stu.SetName("张三");
Console.WriteLine("stu的名字是:" + stu.GetName());
stu.Number = 101;
Console.WriteLine(stu.GetName () + "的学号是:" + stu.Number);
// 派生类可以赋值给基类,但是基类不能赋值给派生类
// Person per = new Student ();
// Student stu1 = new Person ();//会报错
- 在刚才创建的Student类的下方创建练习
练习:定义一个大学生类,继承自学生类,添加独有的属性和方法
class CollegtStu : Student
{
// 添加属性:专业
string subject;
public string Subject
{
get
{
return subject;
}
set
{
subject = value;
}
}
// 添加方法:玩游戏
public void PlayGames()
{
Console.WriteLine("学生时期有很多的时间玩游戏");
}
}
在Main方法中创建大学生对象,使用父类的方法设置姓名SetName
// 定义一个大学生对象,使用父类的方法设置姓名
CollegtStu college = new CollegtStu();
college.SetName("小明");// 继承的传递性
Console.WriteLine(college.GetName () + "是名大学生");
3.3 多态(添加一个新文件Polymorphic,写多态的代码)
在新添加的文件中添加如下代码
using System;
namespace Polymorphic
{
// 定义一个枪类,继承自根类,添加属性和方法
class Gun
{
// 瞄准
public void Loaded()
{
Console.WriteLine("开枪前需要先瞄准");
}
// 开枪
public virtual void Fire()
{
Console.WriteLine("嘣!");
}
}
// 定义一个AK47类,继承自Gun
class AK47 : Gun
{
3.3.1方法替换 -- 在子类中重新实现父类中定义的方法,使用关键字new
public new void Loaded()
{
Console.WriteLine("AK47还需要瞄准?");
}
3.3.2虚方法和重写
- 虚方法 -- 多用于实现多态(使用父类类型,调用子类中实现的方法)
- 用virtual修饰的方法叫做虚方法,用 override修饰的方法叫做重写
- 只有方法和属性才能是虚,字段不能虚
- 在父类中使用关键字 virtual,在子类中重写父类中定义的方法,使用关键字 override
public sealed override void Fire()
{
Console.WriteLine("AK47,哒哒哒……");
}
}
回到program中的Main方法中(别忘了引入命名空间),添加如下代码
Gun gun = new Gun();
gun.Loaded();
gun.Fire();
AK47 ak = new AK47();
ak.Loaded();
ak.Fire();
注释掉之前创建gun的代码,添加如下代码
Gun gun = new AK47();// 把子类对象赋值给父类
gun.Loaded();// 进行了方法替换的,还是调用父类的实现
gun.Fire();// 进行了方法重写的,就调用子类中的实现
- 在刚才创建的新文件Polymorphic,添加如下的代码来讲解密闭性
3.3.3 密封类
- sealed修饰符,修饰类为密封的,不可被继承不可被重写。
- 派生类可以通过sealed来停止继承,内部的方法可以通过sealed来阻止被重写
- sealed是对虚方法或虚属性,也就是同override一起使用,如果不是虚方法或虚属性会报出错误
// 创建一个M56类,继承自AK47
class M56 : AK47
{
// 被sealed修饰的方法,就不能被重写了
// public override void Fire() {
//
// }
}
- 在创建的新文件Polymorphic,添加如下的代码来讲解一下虚方法和重写
- 扩展案例,用于理解 虚方法和重写
class Animal
{
public string Name { get; set; }
public virtual void Eat()
{
Console.Write("{0}正在进食 —— ", Name);
}
}
class Sheep : Animal
{
public Sheep()
{
Name = "羊";
}
public override void Eat()
{
base.Eat();
Console.WriteLine("吃草");
}
}
class Tiger : Animal
{
public Tiger()
{
Name = "老虎";
}
public override void Eat()
{
base.Eat();
Console.WriteLine("吃肉");
}
}
- 回到program中的Main方法中,添加如下代码,来查看虚函数效果
Animal sheep = new Sheep();
Animal tiger = new Tiger();
sheep.Eat();// 调用子类重写的方法
tiger.Eat();// 调用子类重写的方法
本次讲解就到这里,有关技术问题请小伙伴们添加QQ群:941928511,大家一起探讨!
版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明