using System;
namespace lesson1_类和对象
{
#region 面对对象概念回顾
//万物皆对象
//用程序来抽象(形容)对象
//用面对对象思想来编程
#endregion
#region 什么是类
//基本概念
//具有相同特征
//具有相同的行为
//一类事物的抽象
//类是对象的模板
//可以通过类创建出对象
//类的关键词
//class
#endregion
#region 类申明在哪里
//类一般申明在 namespace 语句块中
#endregion
#region 类申明的语法
class 类名
{
//特征--成员变量
//行为--成员方法
//保护特征--成员属性
//构造函数和析构函数
//索引器
//运算符重载
//静态成员
}
#endregion
#region 类申明实例
//这个类是用来形容人类的
//命名:用帕斯卡命名法
//注意:同一个语句块中的不同类 不能重名
class Person
{
//特征--成员变量
//行为--成员方法
//保护特征--成员属性
//构造函数和析构函数
//索引器
//运算符重载
//静态成员
}
class Machine
{
//特征--成员变量
//行为--成员方法
//保护特征--成员属性
//构造函数和析构函数
//索引器
//运算符重载
//静态成员
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("类和对象");
#region 什么是(类)对象
//基本概念
//类的申明 和 类对象(变量)申明是两个概念
//类的申明 类似 枚举 和 结构体的申明 类的申明相当于申明了一个自定义变量类型
//而对象 是类创建出来的
//相当于申明一个指定类的变量
//类创建对象的过程 一般称为实例化对象
//类对象 都是引用类型的
#endregion
#region 实例化对象基本语法
//类名 变量名;
//类名 变量名= null;(null代表空)
//类名 变量名= new 类名();
#endregion
#region 实例化对象
Person p;
Person p2 = null;//null 代表空 不分配堆内存空间
Person p3 = new Person();//相当于一个人对象
Person p4 = new Person();//相当于又是一个人对象
//注意
//虽然他们是来自一个类的实例化对象
//但是他们的 特征 行为等等信息 都是他们独有的
//千万千万 不要觉得他们是共享了数据 两个人 你是你 我是我 彼此没有关系
Machine m = new Machine();
Machine m1 = new Machine();
//面对对象编程 就是开启了 女娲模式 造物模式 想要申明对象 就new申明对象
//一切的对象 都是由我们来控制的
//我们相当于是整个程序世界的 总导演
#endregion
}
}
//总结
//类的申明 和 类对象的申明是两个概念
//类的申明 是申明对象的模板 用来抽象(形容)显示事物的
//类对象的申明 是用来表示现实中的 对象个体的
//类是一个自定义的变量类型
//实例化一个类对象 是在申明变量
}
using System;
namespace lesson_类和对象练习题
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("类和对象练习题");
#region 练习题1
//将下面的事物进行分类,可重复
//机器人、机器、人、猫、张阿姨、隔壁老王、汽车、飞机、向日葵、菊花、太阳、星星、荷花
//机器:机器人、机器、汽车、飞机
//人:人、张阿姨、隔壁老王
//动物:猫、人、张阿姨、隔壁老王
//植物:向日葵、菊花、荷花
//星球:太阳、星星、
#endregion
#region 练习题2
//GameObjectA = new GameObject();
//GameObiectB = A;
//B = null;
//A目前等于多少?
//A等于原来的GameObjec();
#endregion
#region 练习题3
//GameObject A= new GameObject();
//GameObject B= A;
//B = new GameObject();
//A和B有什么关系
#endregion
}
}
}
using System;
namespace lesson2_成员变量和访问修饰符
{
#region 知识回顾
//类和对象
//申明类
//class Person
//{
// //特征--成员变量
// //行为--成员方法
// //保护特征--成员属性
// //构造函数和析构函数
// //索引器
// //运算符重载函数
// //静态函数
//}
// 实例化对象
// Person 变量名;
// Person 变量名 = null;
// Person 变量名 = new Person();
#endregion
#region 成员变量
//基本规则
//1.申明在类语句块中
//2.用来描述对象的特征
//3.可以是任意变量类型
//4.数量不作限制
//5.是否赋值根据需求来定
enum E_SexType
{
Man,
Wonman,
}
struct Position
{
}
class Pet
{
}
class Person
{
//特征--成员变量
//姓名
public string name;
//年龄
public int age;
//性别
public E_SexType sex;
//女朋友
//如果要在类中申明一个和自己相同类型的成员变量时
//不能对它进行实例化
public Person girlFriend;
//朋友
public Person[] boyFriend;
//位置
public Position pos;
//宠物
public Pet pet;
}
#endregion
#region 访问修饰符
// public--公共的 自己(内部)和别人(外部)都能访问和使用
// private--私有的 自己(内部)才能访问和使用 不写 默认为private
// protected--保护的 自己(内部)和子类才能访问和使用
// 目前决定类内部的成员 的 访问权限
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("成员变量和访问修饰符");
Person p = new Person();
#region 成员变量的使用和初始值
//值类型来说 数字类型 默认值都是0 bool类型 false
//引用类型来说 null
//交给大家一个看默认值的小技巧
Console.WriteLine(default(int));
p.age = 10;
Console.WriteLine(p.age);
#endregion
}
}
//总结
//成员变量
//描述特征
//类中申明
//赋值随意
//默认值,值不相同
//默认值,引用为null
//任意类型
//任意数量
//访问修饰符
// public--公共的 自己(内部)和别人(外部)都能访问和使用
// private--私有的 自己(内部)才能访问和使用 不写 默认为private
// protected--保护的 自己(内部)和子类才能访问和使用
}
using System;
namespace lesson2_成员变量和访问修饰符练习题
{
#region 练习题1
//3P是什么?
//访问修饰符
// public--公共的 自己(内部)和别人(外部)都能访问和使用
// private--私有的 自己(内部)才能访问和使用 不写 默认为private
// protected--保护的 自己(内部)和子类才能访问和使用
#endregion
#region 练习题2
//定义一个人类,有姓名,身高,年龄,家庭住址等特征
class Person
{
public string name;
public float height;
public int age;
public string homeAddress;
}
#endregion
#region 练习题3
//定义一个学生类,有姓名,学号,年龄,同桌等特征,有学习方法。用学生类创建若干个学生
class Student
{
public string name;
public int number;
public int age;
public Student deskmate;
}
#endregion
#region 练习题4
//定义一个班级类, 有专业名称,教师容量,学生等。创建一个班级对象
class Class
{
public string name;
public int capacity;
public Student[]students;
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("成员变量和访问修饰符练习题");
#region 创建的对象
/*Person p = new Person();
p.age = 22;
p.name = "黄爱玲";
p.height = 165.5f;
p.homeAddress = "重庆";
Person p1 = new Person();
p1.age = 22;
p1.name = "于双";
p1.height = 170.5f;
p1.homeAddress = "重庆";
Student s = new Student();
s.name = "火山哥";
s.number = 1;
s.age = 22;
Student s1 = new Student();
s1.name = "唐老师";
s1.number = 2;
s1.age = 22;
s.deskmate = s1;
s1.deskmate = s;
Class c = new Class();
c.name = "四班";
c.capacity = 9999;
c.students = new Student[] { s, s1 };*/
#endregion
#region 练习题5
/*Person p = new Person();
p.age = 10;
Person p2 = new Person();
p2.age = 20;
Console.WriteLine(p.age);*/
//请问p.age为多少 ?
//10
#endregion
#region 练习题6
/*Person p = new Person();
p.age = 10;
Person p2 = p;
p2.age = 20;
Console.WriteLine(p.age);*/
//请问p.age为多少?
//20
#endregion
#region 练习题7
/*Student s = new Student();
s.age = 10;
int age = s.age;
age = 20;
Console.WriteLine(s.age);*/
//请问s.age为多少?
//10
#endregion
#region 练习题8
/*Student s = new Student();
s.deskmate = new Student();
s.deskmate.age = 10;
Sudent s2 = s.deskmate;
s2.age = 20;
Console.WriteLine(s.deskmate);*/
//请问s.deskmate.age为多少 ?
//20
#endregion
}
}
}
using System;
namespace lesson3_成员方法
{
#region 成员方法的申明
//基本概念
//成员方法(函数)来表现对象行为
//1.申明在类语句块中
//2.是用来描述对象的行为的
//3.规则和函数申明规则相同
//4.受到访问修饰符规则影响
//5.返回值参数不作限制
//6.方法数量不作限制
//注意
//1.成员方法不要加 static 关键字
//2.成员方法 必须实例化出对象 在通过对象来使用 相当于该对象执行了某个行为
//3.成员方法 受到访问修饰符影响
class Person
{
///
/// 说话的行为
///
/// 说话的内容
public void Speak(string str)
{
Console.WriteLine("{0}说{1}", name, str);
}
///
/// 判断是否成年
///
///
public bool IsAdult()
{
return age >= 18;
}
///
/// 添加朋友的方法
///
/// 传入新朋友
public void AddFriend(Person p)
{
if (friends == null)
{
friends = new Person[] { p };
}
else
{
//扩容
Person[] newFriends = new Person [friends.Length + 1 ];
for (int i = 0; i < friends.Length; i++)
{
newFriends[i] = friends[i];
}
//把新加的朋友放到最后一个
newFriends[newFriends.Length - 1] = p;
//地址重新定向
friends = newFriends;
}
}
public string name;
public int age;
//朋友们
public Person[] friends;
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("成员方法");
#region 成员方法的使用
//2.成员方法 必须实例化出对象 在通过对象来使用 相当于该对象执行了某个行为
Person p = new Person();
p.name = "于双";
p.age = 22;
p.Speak("我爱你");
if (p.IsAdult())
{
p.Speak("我要谈恋爱");
}
Person p2 = new Person();
p2.name = "火山哥";
p2.age = 22;
p.AddFriend(p2);
for (int i = 0; i < p.friends.Length; i++)
{
Console.WriteLine(p.friends[i].name);
}
#endregion
}
}
//总结
//成员方法
//描述行为
//类中申明
//任意数量
//返回值和参数根据需求决定
}
using System;
namespace lesson3_成员方法练习题
{
#region 练习题1
//基于成员变量练习题
//为人类定义说话,走路,吃饭等方法
class Person
{
public string name;
public int age;
public void Speak(string str)
{
Console.WriteLine("{0}岁的{1}说{2}", age, name, str);
}
public void Walk()
{
Console.WriteLine("{0}岁的{1}会走路了",age, name);
}
public void Eat()
{
Console.WriteLine("{0}岁的{1}会吃饭了",age, name);
}
}
#endregion
#region 练习题2
//基于成员变量练习题
//为学生类定义学习,吃饭等方法
class Student
{
public string name;
public int age;
public void Study()
{
Console.WriteLine("{0}岁的{1}在学习", age, name);
}
public void Eat()
{
Console.WriteLine("{0}岁的{1}在吃饭", age, name);
}
}
#endregion
#region 练习题3
//定义一个食物类,有名称,热量等特征
//思考如何和人类以及学生类联系起来
class Food
{
public string name;
public float hot;
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("成员方法练习题");
}
}
}
using System;
namespace lesson4_构造函数和析构函数
{
#region 构造函数
//基本概念
//在实例化对象时 会调用的用于初始化的函数
//如果不写 默认存在一个无参构造函数
//构造函数的写法
//1.没有返回值
//2.函数名和类名必须相同
//3.没有特殊需求时 一般都是public的
class Person
{
public string name;
public int age;
//类中是允许自己申明无参构造函数的
//结构体是不允许
public Person()
{
name = "于双";
age = 18;
}
public Person(int age)
{
//this代表当前调用该函数的对象自己
this.age = age;
}
public Person(string name)
{
//this代表当前调用该函数的对象自己
this.name = name;
}
/*public Person(int age,string name)
{
//this代表当前调用该函数的对象自己
this.age = age;
this.name = name;
}*/
public Person(int age, string name) : this()
{
Console.WriteLine("Person两个参数构造函数调用");
}
~Person()
{
}
}
//4.构造函数可以被重载
//5.this代表当前调用该函数的对象自己
//注意
//如果不自己实现无参构造函数而实现了有参构造函数
//会失去默认的无参构造
#endregion
#region 构造函数特殊写法
//可以通过this 重用构造函数代码
//访问修饰符 构造函数名(参数列表):this(参数1,参数2……)
#endregion
#region 析构函数
//基本概念
//当引用类型的堆内存被回收时,会调用该函数
//对于需要手动管理内存的语言(比如C++),需要在析构函数中做一些内存回收处理
//但是C#中存在自动垃圾回收机制GC
//所以我们几乎不会怎么使用析构函数,除非你想在某一个对象被垃圾回收时,做一些特殊处理
//注意
//在Unity开发中析构函数几乎不会使用,所以该知识点只做了解即可
//基本语法
//~类名()
//{
//}
#endregion
#region 垃圾回收机制
//垃圾回收,英文简写GC(Garbage Collector)
//垃圾回收的过程是在遍历堆(Heap)上动态分配的所有对象
//通过识别它们是否被引用来确定哪些对象是垃圾,哪些对象仍要被使用
//所谓的垃圾就是没有被任何变量,对象引用的内容
//垃圾就需要被回收释放
//垃圾回收有很多种算法,比如
//引用计数(Reference Counting)
//标记清除(Mark Sweep)
//标记整理(Mark Compact)
//复制集合(Copy Ccllection)
//注意
//GC只负责堆(Heap)内存的垃圾回收
//引用类型的是存在堆(Heap)中的,所以它的分配和释放都通过垃圾回收机制来管理
//栈(Stack)上的内存是由系统自动管理的
//值类型在(Stack)中分配内存的,他们有自己的生命周期,不用对他们进行管理,会自动分配和释放
//C#中内存回收机制的大概原理
//0代内存 1代内存 2代内存
//代的概念
//代是垃圾回收机制使用的一种算法(分代算法)
//新分配的对象都会被配置在第0代内存中
//每次分配都可能会进行垃圾回收以释放内存(0代内存满时)
//在一次内存回收过程开始时,垃圾回收器会认为堆中全是垃圾,会进行以下两步
//1.标记对象 从根(静态字段,方法参数)开始检查引用对象,标记后为可达对象,未标记为不可达对象
//不可达对象就认为是垃圾
//2.搬迁对象压缩堆 (挂起执行托管代码线程)释放未标记的对象 搬迁可达对象 修改引用地址
//大对象总被认为是第二代内存 目的是减少性能损耗,提高性能
//不会对大对象进行搬迁压缩 85000字节(83kb)以上的对象为大对象
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("构造函数和析构函数");
Person p = new Person(18,"于双");
Console.WriteLine(p.age);
p = null;
//手动触发垃圾回收的方法
//一般情况下 我们不会频繁调用
//都是在 Loading过场景时才调用
GC.Collect();
}
}
//总结
//构造函数
//实例化对象时 调用的函数
//主要是用来初始化成员变量的
//基本语法
//不写返回值
//函数名和类名相同
//访问修饰符根据需求而定
//一般为public
//注意
//可以重载构造函数
//可以用this语法重用代码
//可以在函数中用this区分同名参数和成员变量
//有参构造会顶掉默认的无参构造
//析构函数
//当对象被垃圾回收时 调用的,主要是用来回收资源或者特殊处理内存的
//基本语法
//不写返回值
//不写修饰符
//不能有参数
//函数名和类名相同
//前面加~
}
using System;
namespace lesson4_构造函数和析构函数练习题
{
#region 练习题1
//基于成员方法练习题
//对人类的构造函数进行重载,用人类创建若干个对象
#endregion
#region 练习题2
//基于成员方法练习题
//堆班级类的构造函数进行重载,用班级类创建若干个对象
#endregion
#region 练习题3
//写一个 Ticket类,有一个距离变量(在构造对象时赋值,不能为负数)
//有一个价格特征,有一个方法GetPrice可以读取到价格,并且根据距离distance计算价格price(1元一公里)
//0到100公里 不打折
//101到200公里 打9.5折
//201到300公里 打9折
//300公里以上 打8折
//有一个显示方法,可以显示这张票的信息
//例如:100公里100块钱
class Ticket
{
uint distance;
float price;
public void GetPrice(uint distance)
{
if (distance < 100)
{
price = distance;
Console.WriteLine("{0}公里{1}块钱",distance,price );
}
if (distance >100 && distance < 200)
{
price = distance * 0.95f;
Console.WriteLine("{0}公里{1}块钱", distance, price);
}
if (distance > 200 && distance < 300)
{
price = distance * 0.9f;
Console.WriteLine("{0}公里{1}块钱", distance, price);
}
if (distance > 300)
{
price = distance*0.8f;
Console.WriteLine("{0}公里{1}块钱", distance, price);
}
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("构造函数和析构函数练习题");
Ticket t = new Ticket();
t.GetPrice(500);
}
}
}
using System;
namespace lesson5_成员属性
{
#region 知识回顾
#endregion
#region 成员属性的基本概念
//基本概念
//1.用于保护成员变量
//2.为成员属性的获取和赋值添加逻辑处理
//3.解决3P的局限性
// public——内外访问
// private——内部访问
// protected——内部和子类访问
//属性可以让成员变量在外部
//只能获取 不能修改 或者 只能修改 不能获取
#endregion
#region 成员属性的基本语法
// 访问修饰 属性类型 属性名
// {
// get{}
// set{}
//
// }
class Person
{
private string name;
private int age;
private int money;
private bool sex;
//属性命名一般使用 帕斯卡命名法 大写开头
public string Name
{
get
{
//为成员属性的获取和赋值添加逻辑处理
//意味着 这个属性可以获取的内容
return name;
}
set
{
//为成员属性的获取和赋值添加逻辑处理
//value 关键字 用于表示 外部传入的值
name = value;
}
}
#region 成员属性中 get和set前可以加访问修饰符
//注意
//1.默认不加 会使用属性申明时的访问权限
//2.加的访问修饰符要低于属性的访问权限
//3.不能让get和set的访问权限都低于属性的权限
#endregion
public int Money
{
get
{
//解密处理
return money - 5;
}
set
{
//加密处理
money = value + 5;
}
}
/*public int Money
{
get
{
return money;
}
set
{
if (value < 0)
{
value = 0;
Console.WriteLine("钱不能少于0,强制设置为0了");
}
money = value;
}
}*/
#region 成员属性中 get和set前可以加访问修饰符
//注意
//1.默认不加 会使用属性申明时的访问权限
//2.加的访问修饰符要低于属性的访问权限
//3.不能让get和set的访问权限都低于属性的权限
#endregion
#region get和set可以只有一个
//注意
//只有一个时 没必要在前面加访问修饰符
//一般情况下 只会出现 只有get的情况 基本不会出现只有set
public bool Sex
{
get
{
return sex;
}
/*set
{
sex = value;
}*/
}
#endregion
#region 自动属性
//作用:外部能得不能改的特征
//如果类中有一个特征是只希望外部能得到不能改的 又没什么特殊处理
//那么可以直接使用特殊属性
public float Height
{
//没有在get和set中写逻辑的需求或想法
get;
set;
}
#endregion
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("成员属性");
#region 成员属性的使用
Person p = new Person();
p.Name = "于双";
Console.WriteLine(p.Name);
p.Money = 1000;
Console.WriteLine(p.Money);
//Console.WriteLine(p.Sex);
//p.Sex = false;
#endregion
}
}
//总结
//1.成员属性概念:一般是用来保护成员变量的
//2.成员属性的使用和变量一样 外部用对象点出
//3.get中需要return内容 ;set中要用value表示传入的内容
//4.get和set语句块中可以加逻辑处理
//5.get和set可以加访问修饰符 但是要按一定规则进行添加
//6.get和set可以只有一个
//7.自动属性是属性语句块中只有get和set,一般用于 外部能不能改的这种情况
}
using System;
namespace lesson5_成员属性练习题
{
#region 练习题1
//定义一个学生类,有五种属性,分别为姓名、性别、年龄、CSharp成绩、Unity成绩
//有两个方法:
//一个打招呼:介绍自己叫XX,今年几岁了,是男同学还是女同学
//计算自己总分数和平均分并显示的方法
//使用属性完成:年龄必须是0 ~150岁之间,成绩必须是0 ~100
//性别只能是男或女
//实例化两个对象并测试
class Student
{
public string name;
private string sex;
private int age;
private float csharp;
private float unity;
public string Sex
{
get
{
return sex;
}
set
{
if (value=="男"||value=="女")
{
sex = value;
}
else
{
Console.WriteLine("请输入正确的性别!");
}
}
}
public int Age
{
get
{
return age;
}
set
{
if (value < 0 || value > 150)
{
Console.WriteLine("请输入正确的年龄!");
}
age = value;
}
}
public float Csharp
{
get
{
return csharp;
}
set
{
if (value < 0 || value > 100)
{
Console.WriteLine("请输入正确的成绩!");
}
csharp = value;
}
}
public float Unity
{
get
{
return unity;
}
set
{
if (value < 0 || value > 100)
{
Console.WriteLine("请输入正确的成绩!");
}
unity = value;
}
}
public void Sum()
{
float sum,avg;
sum = csharp + unity;
avg = sum / 2;
Console.WriteLine("成绩总和为{0} 成绩平均数为{1}", sum, avg);
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("成员属性练习题");
Student s = new Student();
Console.WriteLine("请问你叫什么名字?");
s.name = Console.ReadLine();
Console.WriteLine("请问你多少岁了?");
s.Age = int.Parse(Console.ReadLine());
Console.WriteLine("请问你是男同学还是女同学?");
s.Sex =Console.ReadLine();
Console.WriteLine("请输入你的CSharp成绩");
s.Csharp = float.Parse(Console.ReadLine());
Console.WriteLine("请输入你的Unity成绩");
s.Unity = float.Parse(Console.ReadLine());
s.Sum();
}
}
}
using System;
namespace lesson6_索引器
{
#region 知识回顾
#endregion
#region 索引器基本概念
//基本概念
//让对象可以像数组一样通过索引访问其中元素,使程序看起来更直观,更容易编写
#endregion
#region 索引器语法
// 访问修饰符 返回值 this(参数类型 参数名,参数类型 参数名……)
// {
// 内部的写法和规则和索引器相同
// get{}
// set{}
// }
class Person
{
private string name;
private int age;
private Person[] friends;
private int[,] array;
#region 索引器可以重载
//重载的概念是——函数名相同 参数类型、数量、顺序不同
public int this[int i, int j]
{
get
{
return array[i, j];
}
set
{
array[i, j] = value;
}
}
public string this[string str]
{
get
{
switch (str)
{
case "name":
return this.name;
case "age":
return age.ToString();
}
return "";
}
set
{
}
}
#endregion
public Person this[int index]
{
get
{
//可以写逻辑的 根据需求来处理这里面的内容
#region 索引器中可以写逻辑
if (friends == null ||friends.Length-1 friends.Length - 1)
{
//自己定了一个规则 如果索引越界 就默认把最后一个朋友顶掉
friends[friends.Length - 1] = value;
}
friends[index] = value;
}
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("索引器");
#region 索引器的使用
Person p = new Person();
p[0]= new Person();
Console.WriteLine(p[0]);
p[0, 0] = 10;
#endregion
}
}
//总结
//索引器对于我们来说的主要作用
//可以让我们以中括号的形式范围自定义类中的元素 规则自己定 访问时和数组一样
//比较适用于 在类中有数组变量时使用 可以方便的访问和进行逻辑处理
//固定写法
//访问修饰符 返回值 this[参数列表]
//get和set语句块
//可以重载
//注意:结构体里面也支持索引器
}
using System;
namespace lesson6_索引器练习题
{
#region 练习题1
//自定义一个整型数组类,该类中有一个整形数组变量
//为它封装增删查改的方法
class Array
{
private int[] array= { 1,2,3,4,5,6};
public int this[int a]
{
get
{
return array[a];
}
set
{
array[a] = value;
}
}
//增
public int[] Zeng(int a)
{
int[] array2=new int[array.Length+1];
for (int i = 0; i < array.Length; i++)
{
array2[i] = array[i];
}
array2[array2.Length] = a;
return array2;
}
//删
public int[] Shan(int a)//a代表删除的数
{
int[] array2 = new int[array.Length];
int j=0;
for (int i = 0; i < array.Length; i++)
{
if (array[i] == a)
{
j = i;
break;
}
}
for(int i = 0; i < array.Length; i++)
{
if (j == i)
{
continue;
}
else
{
array2[i] = array[i];
}
}
return array2;
}
//查
public void Cha(int a)
{
for (int i = 0; i < array.Length; i++)
{
if (array[i] == a)
{
Console.WriteLine("和{0}相等的元素在{1}索引位置", a, i);
}
}
}
//改
public int[] Gai(int a, int b)//a代表要改的索引号,b代表改成的数
{
array[a] = b;
return array;
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("索引器练习题");
Array a = new Array();
a.Gai(0, 3);
a.Shan(3);
Console.WriteLine(a[0]);
}
}
}
7.静态成员
using System;
namespace lesson7_静态成员
{
#region 1 静态成员的基本概念
//静态关键字 static
//用static修饰的 成员变量、方法、属性等
//称为静态成员
//静态成员的特点是:直接使用类名点出使用
#endregion
#region 2早已出现的静态成员
#endregion
#region 3自定义静态成员
class Test
{
//静态成员变量
public static float PI = 3.1415926f;
//成员变量
public int testInt = 100;
//静态成员方法
public static float CalcCircle(float r)
{
#region 6静态函数中不能使用非静态成员
//成员变量只能将对象实例化出来后 才能点出来使用 不能无中生有
//不能直接使用 非静态成员 否则会报错
#endregion
return PI * r * r;
}
//成员方法
public void TestFun()
{
#region 7非静态函数可以使用静态成员
Console.WriteLine(PI);
Console.WriteLine(CalcCircle(2));
#endregion
Console.WriteLine("123");
}
}
#endregion
#region 5为什么可以直接点出来使用
//记住
//程序中是不能无中生有的
//我们要使用的对象,变量,函数都是要在内存分配中分配内存空间的
//之所以要实例化对象,目的就是分配内存空间,在程序中产生一个抽象的对象
//静态成员的特点
//程序开始运行时,就会分配内存空间,所以我们就能直接使用
//静态成员和程序同生共死
//只要使用了它,直到程序结束时才会释放
//所以静态成员就会有自己唯一的一个“内存小房间”
//这让静态成员就有了唯一性
//在任何地方使用都是用的小房间里的内容,改变了它也是改变小房间里的内容
#endregion
#region 8静态成员对于我们的作用
//静态变量:
//1.常用唯一变量的申明
//2.方便别人获取的对象申明
//静态方法:
//常用的唯一的方法申明 比如 相同规则的数学计算相关函数
#endregion
#region 9常量和静态变量
//const (常量)可以理解为特殊的static(静态)
//相同点
//他们都可以通过类名点出使用
//不同点
//1.const必须初始化,不能修改 static没有这个规则
//2.const只能修饰变量,static可以修饰很多
//3.const一定是写在访问修饰符后面的,static没有这个要求
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("静态成员");
#region 4静态成员的使用
Console.WriteLine(Test.PI);
Console.WriteLine(Test.CalcCircle(2));
Test t = new Test();
Console.WriteLine(t.testInt);
t.TestFun();
#endregion
}
}
//总结
//概念:用static修饰的成员变量、成员方法、成员属性等 就称为静态成员
//特点:直接用类名点出来使用
//生命周期:和程序同生共死
// 程序运行后就会一直存在内存中,直到程序结束后才会释放,因此静态成员具有唯一性
//注意:
//1.静态函数中不能使用非静态成员
//2.非静态函数可以使用静态成员
//常量和静态变量
//常量是特殊的静态变量
//相同点
//他们都可以通过类名点出使用
//不同点
//1.const必须初始化,不能修改 static没有这个规则
//2.const只能修饰变量,static可以修饰很多
//3.const一定是写在访问修饰符后面的,static没有这个要求
}
using System;
namespace lesson7_静态成员练习题
{
#region 练习题1
//请说出const和static的区别
//const (常量)可以理解为特殊的static(静态)
//相同点
//他们都可以通过类名点出使用
//不同点
//1.const必须初始化,不能修改 static没有这个规则
//2.const只能修饰变量,static可以修饰很多
//3.const一定是写在访问修饰符后面的,static没有这个要求
#endregion
#region 练习题2
//请用静态成员相关知识实现
//一个类对象,在整个应用程序的生命周期中,有且仅会有一个该对象的存在
//不能在外部实例化,直接通过该类类名就能够得到唯一的对象
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("静态成员练习题");
}
}
}
using System;
namespace lesson8_静态类和静态构造函数
{
#region 静态类
//概念:用static修饰的类
//特点:只能包含静态成员,不能被实例化
//作用
//1.将常用的静态成员写在静态类中 方便使用
//2.静态类不能被实例化,更能体现工具类的 唯一性
//例如 Console就是一个静态类
static class Tools
{
public static int testIndex = 0;
public static void TestFun()
{
}
public static int TestIndex
{
get;
set;
}
}
#endregion
#region 静态构造函数
//概念
//在构造函数加上 static 修饰
//特点
//1.静态类和普通类都可以有
//2.不能使用访问修饰符
//3.不能有参数
//4.只会调用一次
//作用
//在静态函数中初始化 静态变量
//使用
//1.静态类中的静态构造函数
static class StaticClass
{
public static int testInt = 100;
public static int testInt2 = 100;
static StaticClass()
{
Console.WriteLine("静态构造函数");
testInt = 200;
testInt2 = 300;
}
}
//2.普通类中的静态构造函数
class Test
{
public static int testInt = 200;
static Test()
{
Console.WriteLine("静态构造函数");
}
public Test()
{
Console.WriteLine("普通构造");
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("静态类和静态构造函数");
Console.WriteLine(StaticClass.testInt);
Console.WriteLine(StaticClass.testInt2);
Console.WriteLine(StaticClass.testInt);
Console.WriteLine(Test.testInt);
Test t = new Test();
Test t2 = new Test();
}
}
//总结
//静态类
//用static 修饰的类
//特点:只能包含静态成员,不能被实例化
//作用
//1.将常用的静态成员写在静态类中 方便使用
//2.静态类不能被实例化,更能体现工具类的 唯一性
//静态构造函数
//在构造函数加上 static 修饰
//特点
//1.静态类和普通类都可以有
//2.不能使用访问修饰符
//3.不能有参数
//4.只会调用一次
}
using System;
namespace lesson8_静态类和静态构造函数练习题
{
#region 练习题1
//写一个用于数学计算的静态类
//该类中提供计算圆面积,圆周长,矩形面积,周长,取一个数的绝对值等方法
static class Test
{
static float PI = 3.1415926f;
public static float r;
public static float c;
public static float k;
static Test()
{
Console.WriteLine("圆面积为{0} 圆周长为{1}", PI * r * r, PI * r * 2);
Console.WriteLine("矩形面积为{0} 矩形周长为{1}", c * k, 2 * (c + k));
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("静态类和静态构造函数练习题");
Console.WriteLine(Test.r);
}
}
}
using System;
namespace lesson9_拓展方法
{
#region 拓展方法基本概念
//概念
//为现有非静态 变量类型 添加 新方法
//作用
//1.提升程序拓展性
//2.不需要在对象中重新写方法
//3.不需要继承来添加方法
//4.为别人封装的类型写额外的方法
//特点
//1.一定是写在静态类中
//2.一定是个静态函数
//3.第一个参数为拓展目标
//4.第一个参数用this修饰
#endregion
#region 基本语法
//访问修饰符 static 返回值 函数名(this 拓展类名 参数名,参数类型 参数名,参数类型 参数名……)
#endregion
#region 实例
static class Tools
{
//为int拓展了一个成员方法
//成员方法 是需要 实例化对象后 才能使用的
//value 代表 使用该方法的 实例化对象
public static void SpeakValue(this int value)
{
//拓展方法的逻辑
Console.WriteLine("为int拓展的方法" + value);
}
public static void SpeakStringInfo(this string str, string str2, string str3)
{
Console.WriteLine("为string拓展的方法");
Console.WriteLine("调用方法的对象" + str);
Console.WriteLine("传的参数" + str2+str3);
}
public static void Fun3(this Test t)
{
Console.WriteLine("为Test拓展的方法");
}
}
#endregion
#region 为自定义的类型拓展方法
class Test
{
public int i = 10;
public void Fun()
{
Console.WriteLine("123");
}
public void Fun2()
{
Console.WriteLine("456");
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("拓展方法");
#region 使用
int i = 10;
i.SpeakValue();
string str = "000";
str.SpeakStringInfo("于双", "222");
Test t = new Test();
t.Fun3();
#endregion
}
}
//总结
//概念:为现有的非静态类 变量类型 添加 方法
//作用:
//提升程序拓展性
//不需要在对象中重新写方法
//不需要继承来添加方法
//为别人封装的类型写额外的方法
//特点
//静态类中的静态方法
//第一个参数为拓展目标
//第一个参数用this修饰
//注意
//可以有返回值和n个参数
//根据需求而定
}
using System;
namespace lesson9_拓展方法练习题
{
#region 练习题1
//为整形拓展一个求平方的方法
static class Toos
{
static void A(this int i)
{
Console.WriteLine("该整形的平方为{0}", i * i);
}
}
#endregion
#region 练习题2
//写一个玩家类,包含姓名,血量,攻击力,防御力等特征,攻击,移动,受伤等方法
//为该玩家类拓展一个自杀的方法
static class Player
{
public static string name;
static int hp =100;
static int atk =10;
static int def =5;
static int hurt;
public static void Atk()
{
Console.WriteLine("{0}攻击了对方", name);
}
public static void Move()
{
Console.WriteLine("{0}移动了", name);
}
public static void Hurt(int hurt)
{
hp -= hurt;
Console.WriteLine("{0}受到了{1}点伤害,还剩下{2}点血", name,hurt,hp);
}
public static void Kill(this int hp)
{
hp = 0;
Console.WriteLine("{0}自杀了", name);
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("拓展方法练习题");
Player.name = "于双";
Player.Hurt(50);
int hp = 100;
hp.Kill();
}
}
}
using System;
namespace lesson10_运算符重载
{
#region 基本概念
//概念
//让自定义类和结构体
//能够使用运算符
//使用关键字
//operator
//特点
//1.一定是一个公共的静态方法
//2.返回值写在operator前
//3.逻辑处理自定义
//作用
//让自定义类和结构体对象可以进行运算
//注意
//1.条件运算符需要成对实现
//2.一个符号可以多个重载
//3.不能使用ref和out
#endregion
#region 基本语法
//public static 返回类型 operator 运算符(参数列表)
#endregion
#region 实例
class Point
{
public int x;
public int y;
public static Point operator +(Point p1,Point p2)
{
Point p = new Point();
p.x = p1.x + p2.x;
p.y = p1.y + p2.y;
return p;
}
public static Point operator +(Point p1, int value)
{
Point p = new Point();
p.x = p1.x + value;
p.y = p1.y + value;
return p;
}
public static Point operator +(int value , Point p1)
{
Point p = new Point();
p.x = p1.x + value;
p.y = p1.y + value;
return p;
}
#region 可重载和不可重载的运算符
#region 可重载的运算符
#region 算术运算符
//注意 符号需要两个参数还是一个参数
public static Point operator -(Point p1, Point p2)
{
return null;
}
public static Point operator *(Point p1, Point p2)
{
return null;
}
public static Point operator /(Point p1, Point p2)
{
return null;
}
public static Point operator %(Point p1, Point p2)
{
return null;
}
public static Point operator ++(Point p1)
{
return null;
}
public static Point operator --(Point p1)
{
return null;
}
#endregion
#region 逻辑运算符
//注意 符号需要两个参数还是一个参数
public static bool operator !(Point p1)
{
return false;
}
#endregion
#region 位运算符
//注意 符号需要两个参数还是一个参数
public static Point operator |(Point p1, Point p2)
{
return null;
}
public static Point operator &(Point p1, Point p2)
{
return null;
}
public static Point operator ^(Point p1, Point p2)
{
return null;
}
public static Point operator ~(Point p1)
{
return null;
}
public static Point operator <<(Point p1, int num)
{
return null;
}
public static Point operator >>(Point p1, int num)
{
return null;
}
#endregion
#region 条件运算符
//1.返回值一般是bool值 也可以是其他的
//2.相关符号必须配对实现
public static bool operator >(Point p1, Point p2)
{
return false;
}
public static bool operator <(Point p1, Point p2)
{
return false;
}
public static bool operator >=(Point p1, Point p2)
{
return false;
}
public static bool operator <=(Point p1, Point p2)
{
return false;
}
public static bool operator ==(Point p1, Point p2)
{
return false;
}
public static bool operator !=(Point p1, Point p2)
{
return false;
}
#endregion
#endregion
#region 不可重载的运算符
//逻辑与(&&) 逻辑或(||)
//索引符[]
//强转运算符()
//特殊运算符
//点. 三目运算符? : 赋值符号=
#endregion
#endregion
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("运算符重载");
#region 使用
Point p = new Point();
p.x = 1;
p.y = 1;
Point p2 = new Point();
p2.x = 1;
p2.y = 1;
Point p3 = p + p2;
Point p4 = p3 + 4;
Point p5 = 4 + p4;
#endregion
}
}
//总结
//关键字
//operator
//固定语法
//public static 返回值 operator 运算符(参数列表)
//作用:
//让自定义类和结构体对象 进行运算
//注意:
//1.参数的数量
//2.条件运算符的配对实现
//3.一个符号可以多个重载
//4.不能用ref和out
}
using System;
namespace lesson10_运算符重载练习题
{
#region 练习题1
//定义一个位置结构体或类,为其重载判断是否相等的运算符
//(x1,y1)==(x2,y2) =>两个值同时相等才为true
class Vector2
{
public int x;
public int y;
public static bool operator ==(Vector2 v1, Vector2 v2)
{
return v1.x==v2.x && v1.y==v2.y;
}
public static bool operator !=(Vector2 v1, Vector2 v2)
{
return v1.x == v2.x && v1.y == v2.y;
}
}
#endregion
#region 练习题2
//定义一个Vector3类(x,y,z)通过重载运算符实现以下运算
//(x1,y1,z1)+(x2,y2,z2)=(x1+x2,y1+y2,z1+z2)
//(x1,y1,z1)-(x2,y2,z2)=(x1-x2,y1-y2,z1-z2)
//(x1,y1,z1)*num=(x1*num,y1*num,z1*num)
class Vector3
{
public int x;
public int y;
public int z;
public static Vector3 operator +(Vector3 v1, Vector3 v2)
{
Vector3 v = new Vector3();
v.x = v1.x + v2.x;
v.y = v1.y + v2.y;
v.z = v1.z + v2.z;
return v;
}
public static Vector3 operator -(Vector3 v1, Vector3 v2)
{
Vector3 v = new Vector3();
v.x = v1.x - v2.x;
v.y = v1.y - v2.y;
v.z = v1.z - v2.z;
return v;
}
public static Vector3 operator *(Vector3 v1, int num)
{
Vector3 v = new Vector3();
v.x = v1.x*num;
v.y = v1.y * num;
v.z = v1.z * num;
return v;
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("运算符重载练习题");
Vector2 v1 = new Vector2();
v1.x = 2;
v1.y = 3;
Vector2 v2 = new Vector2();
v2.x = 2;
v2.y = 3;
if (v1 == v2)
{
Console.WriteLine(true);
}
else
{
Console.WriteLine(false);
}
}
}
}
using System;
namespace lesson11_内部类和分部类
{
#region 内部类
//概念
//在一个类中再申明一个类
//特点
//使用时要用包裹者点出自己
//作用
//亲密关系的变现
//注意
//访问修饰符作用很大
class Person
{
public int age;
public string name;
public Body body;
public class Body
{
Arm leftArm;
Arm rightArm;
class Arm
{
}
}
}
#endregion
#region 分部类
//概念
//把一个类分成几部分申明
//关键字
//partial
//作用
//分部描述一个类
//增加程序的拓展性
//注意
//分部类可以协助多个脚本文件中
//分部类的访问修饰符要一致
//分部类中不能有重复成员
partial class Student
{
public bool sex;
public string name;
partial void Speak();
}
partial class Student
{
public int number;
partial void Speak()
{
//实现逻辑
}
public void Speak(string str)
{
}
}
#endregion
#region 分部方法
//概念
//将方法的申明和实现分离
//特点
//1.不能加访问修饰符 默认私有
//2.只能在分部类中申明
//3.返回值只能是void
//4.可以有参数但不用out关键字
//局限性很大,了解即可
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("内部类和分部类");
Person p = new Person();
Person.Body body = new Person.Body();
Student s = new Student();
}
}
}
using System;
namespace lesson12_继承_继承的基本规则
{
#region 基本概念
//一个类A继承一个类B
//类A将会继承类B的所有成员
//A类将拥有B类的所有特征和行为
//被继承的类
//称为 父类、基类、超类
//继承的类
//称为子类、派生类
//子类可以有自己的特征和行为
//特点
//1.单根性 子类只能有一个父类
//2.传递性 子类可以间接继承父类的父类
#endregion
#region 基本语法
// class 类名 : 被继承的类名
// {
//
// }
#endregion
#region 实例
class Teacher
{
public string name;//名字
public int number;//职工号
//介绍名字
public void SpeakName()
{
Console.WriteLine(name);
}
}
class TeachingTeacher : Teacher
{
public string subject;//科目
//介绍科目
public void SpeakSubject()
{
Console.WriteLine(subject+"老师");
}
}
class ChineseTeacher : TeachingTeacher
{
public void Skill()
{
Console.WriteLine("一行白鹭上青天");
}
}
#endregion
#region 访问修饰符的影响
//public -- 公共 内外部访问
//private -- 私有 内部访问
//protected -- 保护 内部和子类访问
//之后讲命名空间的时候讲
//intternal--内部的 只有在同一个程序集的文件中,内部类型或者是成员才可以访问
#endregion
#region 子类和父类的同名成员
//概念
//C#中允许存在和父类同名的成员
//但是 极不建议使用
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("继承_继承的基本规则");
TeachingTeacher tt = new TeachingTeacher();
tt.name = "于双";
tt.number = 1;
tt.SpeakName();
tt.subject = "Unity";
tt.SpeakSubject();
ChineseTeacher ct = new ChineseTeacher();
ct.name = "于双";
ct.number = 2;
ct.subject = "语文";
ct.SpeakName();
ct.SpeakSubject();
ct.Skill();
}
}
//总结
//继承基本语法
//class 类名 : 被继承的类名
//1.单根性 子类只能有一个父类
//2.传递性 子类可以间接继承父类的父类
//3.访问修饰符 对于成员的影响
//4.极不建议使用 在子类中申明和父类同名的成员(以后学习了多态再来解决这个问题)
}
using System;
namespace lesson12_继承_继承的基本规则练习题
{
#region 练习题
//写一个人类,人类中有姓名,年龄属性,有说话行为
//战士类继承人类,有攻击行为
class Person
{
public string name;
public int age;
public void Speak()
{
Console.WriteLine("{0}岁的{1}说话了", age, name);
}
}
class Warrior : Person
{
public void Atk()
{
Console.WriteLine("{0}发动了攻击", name);
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("继承的基本规则练习题");
Warrior w = new Warrior();
w.name = "战士";
w.Atk();
}
}
}
using System;
namespace lesson13_继承_里氏替换原则
{
#region 基本概念
//里氏替换原则是面向对象七大原则中最重要的原则
//概念:
//任何父类出现的地方,子类都可以替代
//重点:
//语法表现--父类容器装子类对象,因为子类对象包含了父类所有的内容
//作用:
//方便精选对象的存储和管理
#endregion
#region 基本实现
class GameObject
{
}
class Player : GameObject
{
public void PlayerAtk()
{
Console.WriteLine("玩家攻击");
}
}
class Monster : GameObject
{
public void MonsterAtk()
{
Console.WriteLine("怪物攻击");
}
}
class Boss:GameObject
{
public void BossAtk()
{
Console.WriteLine("Boss攻击");
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("里氏替换原则");
//里氏替换原则 用父类容器 装载子类对象
GameObject player = new Player();
GameObject monster=new Monster();
GameObject boss = new Boss();
GameObject[] objects = new GameObject[] { new Player(), new Monster(), new Boss() };
#region is和as
//基本概念
//is:判断一个对象是否是指定类对象
//返回值:bool 是为真 不是为假
//as:将一个对象转换为指定类对象
//返回值:指定类型对象
//成功返回指定类型对象,失败返回null
//基本语法
//类对象 is 类名 该语句块 会有一个bool返回值 true和false
//类对象 as 类名 该语句块 会有一个对象返回值 对象和null
if (player is Player)
{
Player p = player as Player;
p.PlayerAtk();
//简写
(player as Player).PlayerAtk();
}
for (int i = 0; i < objects.Length; i++)
{
if (objects[i] is Player)
{
(objects[i] as Player).PlayerAtk();
}
else if (objects[i] is Monster)
{
(objects[i] as Monster).MonsterAtk();
}
else if (objects[i] is Boss)
{
(objects[i] as Boss).BossAtk();
}
}
#endregion
}
}
//总结
//概念:父类容器装子类对象
//作用:方便进行对象的存储和管理
//使用:is和as
// is 用于判断
// as 用于转换
//注意:不能用子类装父类对象
}
using System;
namespace lesson13_继承_里氏替换原则练习题
{
#region 练习题1
//is和as的区别是什么
//is:判断一个对象是否是指定类对象
//返回值:bool 是为真 不是为假
//as:将一个对象转换为指定类对象
//返回值:指定类型对象
//成功返回指定类型对象,失败返回null
#endregion
#region 练习题2
//写一个Monster类,它派生出Boss和Goblin两个类,Boss有技能:小怪有攻击;
//随机生成10个怪,装载到数组中,遍历这个数组,调用他们的攻击方法
//如果是Boss就释放技能
class Monster
{
public string name;
}
class Boss : Monster
{
public string skill;
public void BossAtk()
{
Console.WriteLine("Boss{0}释放了{1}技能", name, skill);
}
}
class Goblin : Monster
{
public void GoblinAtk()
{
Console.WriteLine("Goblin{0}发动了攻击", name);
}
}
#endregion
#region 练习题3
//FPS游戏模拟
//写一个玩家类,玩家可以拥有各种武器
//现在有四种武器,冲锋枪,散弹枪,手枪,匕首
//玩家默认拥有匕首
//请在玩家类中写一个方法,可以拾取不同的武器替换自己拥有的枪械
class Weapon
{
}
//冲锋枪
class SubmachineGun : Weapon
{
}
//散弹枪
class ShotGun : Weapon
{
}
//手枪
class Pistol : Weapon
{
}
//匕首
class Dagger : Weapon
{
}
class Player
{
private Weapon nowHaveWeapon;
public Player()
{
nowHaveWeapon = new Dagger();
}
public void PickUp(Weapon weapon)
{
nowHaveWeapon = weapon;
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("里氏替换原则练习题");
#region 练习题2
Monster Boss = new Boss();
Monster Goblin = new Goblin();
Monster[] monsters = new Monster[10];
int[] a = new int[monsters.Length];
for (int i = 0; i < a.Length; i++)
{
Random rd = new Random();
int sjs = rd.Next(0, 2);
a[i] = sjs;
if (a[i] == 0)
{
monsters[i] = new Boss();
}
else if (a[i] == 1)
{
monsters[i] = new Goblin();
}
Console.WriteLine(a[i]);
}
for (int i = 0; i < monsters.Length; i++)
{
if (monsters[i] is Boss)
{
(monsters[i] as Boss).name = "小七";
(monsters[i] as Boss).skill = "恶龙咆哮";
(monsters[i] as Boss).BossAtk();
}
else if (monsters[i] is Goblin)
{
(monsters[i] as Goblin).name = "佩玖";
(monsters[i] as Goblin).GoblinAtk();
}
}
#endregion
#region 练习题3
Player p = new Player();
SubmachineGun s = new SubmachineGun();
p.PickUp(s);
ShotGun sg = new ShotGun();
p.PickUp(sg);
#endregion
}
}
}
using System;
namespace lesson14_继承_继承中的构造函数
{
#region 继承中的构造函数 基本概念
//特点
//当申明一个子类对象时
//先执行父类的构造函数
//再执行子类的构造函数
//注意:
//1.父类的无参构造 很重要
//2.子类可以通过base关键字 代表父类 调用父类构造
#endregion
#region 继承中的构造函数的执行顺序
//父类的父类构造——>...父类构造——>子类构造
class GameObject
{
public GameObject()
{
Console.WriteLine("GameObject的构造函数");
}
}
class Player : GameObject
{
public Player()
{
Console.WriteLine("Player的构造函数");
}
}
class MainPlayer : Player
{
public MainPlayer()
{
Console.WriteLine("MainPlayer的构造函数");
}
}
#endregion
#region 父类的无参构造很重要
//子类实例化时,默认自动调用的 是父类的无参构造 所以如果父类无参构造被顶掉 会报错
class Father
{
/*public Father()
{
}*/
public Father(int i)
{
Console.WriteLine("Father构造");
}
}
class Son : Father
{
#region 通过base调用指定父类构造
public Son(int i):base(i)
{
Console.WriteLine("Son的一个参数的构造");
}
public Son(int i, string str) : this(i)
{
Console.WriteLine("Son的两个参数的构造");
}
#endregion
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("继承中的构造函数");
MainPlayer mp = new MainPlayer();
Son s = new Son(1,"123");
}
}
//总结
//继承中的构造函数
//特点
//执行顺序 是先执行父类的构造函数 再执行子类的
//父类中的无参构造函数 很重要
//如果被顶掉 子类中就无法默认调用无参构造了
//解决方法:
//1.始终保持申明一个无参构造
//2.通过base关键字 调用指定父类的构造
//注意:
//区分this和base的区别
//this是代表自己的另一个构造函数
//base是代表父类的另一个构造函数
}
using System;
namespace lesson14_继承_继承中的构造函数练习题
{
#region 练习题
//有一个打工人基类,有工种,工作内容两个特征,一个工作方法
//程序员、策划、美术分别继承打工人
//请用继承中的构造函数这个知识点
//实例化3个对象,分别是程序员、策划、美术
class Worker
{
public string name;
public string type;
public string work;
public Worker()
{
Console.WriteLine("工作方法");
}
}
class ItMan: Worker
{
public ItMan(string name)
{
Console.WriteLine("{0}IT工作方法",name);
}
}
class PlanMan: Worker
{
public PlanMan(string name)
{
Console.WriteLine("{0}Plan工作方法", name);
}
}
class ArtMan: Worker
{
public ArtMan(string name)
{
Console.WriteLine("{0}ART工作方法", name);
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("继承中的构造函数练习题");
ItMan i = new ItMan("松松");
PlanMan p = new PlanMan("爱玲");
ArtMan a = new ArtMan("阿哲");
}
}
}
using System;
namespace lesson15_继承_万物之父和装箱拆箱
{
#region 里氏替换原则回顾
//概念:父类容器装子类对象
//作用:方便进行对象存储和管理
//使用:
//is和as
//is用于判断
//as用于转换
class Father
{
}
class Son : Father
{
public void Speak()
{
}
}
#endregion
#region 万物之父的基本概念
//万物之父
//关键字:object
//概念:
//object是所有类型的基类,它是一个类(引用类型)
//作用:
//1.可以用里氏替换原则,用object同期装所有对象
//2.可以用来表示不确定类型,作为函数参数类型
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("万物之父和装箱拆箱");
#region 万物之父的使用
Father f = new Son();
if (f is Son)
{
(f as Son).Speak();
}
//引用类型
object o = new Son();
//用is as 来判断和转换即可
if (o is Son)
{
(o as Son).Speak();
}
//值类型
object o2 = 1;
//用强转
float fl = (float)o2;
//特殊的string类型
object str = "123123";
string str2 = str as string;
//数组
int[] arr = new int[10];
int[] ar = arr as int[];
#endregion
#region 装箱拆箱
//发生条件
//用object存值类型(装箱)
//再把object转为值类型(拆箱)
//装箱
//把值类型引用类型存储
//栈内存会迁移到堆内存中
//拆箱
//把引用类型存储的值类型取出来
//堆内存会迁移到栈内存中
//好处:不确定类型时方便参数的存储和传递
//坏处:存在内存迁移,增加性能消耗
//装箱
object v = 3;
//拆箱
int intValue = (int)v;
TestFun(1, 2, 3, 4f, "123456789", new Son());
#endregion
}
static void TestFun(params object[] array)
{
}
}
//总结
//万物之父:object
//基于里氏替换原则的 可以用object容器装载一切类型的变量
//它是所有类型的基类
//装箱拆箱
//用object存值类型(装箱)
//把object里面存的值 转换出来(拆箱)
//好处:不确定类型时方便参数的存储和传递
//坏处:存在内存迁移,增加性能消耗
//不是不用 尽量少用
}
using System;
namespace lesson15_继承_万物之父和装箱拆箱练习题
{
#region 练习题1
//请口头描述什么是装箱拆箱
//用object存值类型(装箱)
//把object里面存的值 转换出来(拆箱)
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("万物之父和装箱拆箱练习题");
#region 练习题2
//请用代码描述装箱拆箱
//装箱
object v = 3;
//拆箱
int intValue = (int)v;
#endregion
}
}
}
using System;
namespace lesson16_继承_密封类
{
#region 基本概念
//密封类 是使用 sealed密封关键字修饰的类
//作用:让类无法再被继承
#endregion
#region 实例
sealed class Father
{
}
/*class Son : Father
{
}*/
//父类有sealed关键字,不可被继承
#endregion
#region 作用
//在面向对象程序的设计中,密封类的主要作用就是不允许最底层子类被继承
//可以保证程序的规范性,安全性
//目前对于大家来说,可能用处不大
//随着大家的成长,以后制作复杂系统或者程序框架时 便能慢慢体会到密封类的作用
#endregion
//总结
//关键字:sealed
//作用:让类无法被继承
//意义:加强面向对象程序设计的 规范性、结构性、安全性
class Program
{
static void Main(string[] args)
{
Console.WriteLine("密封类");
}
}
}
using System;
namespace lesson16_继承_综合练习题
{
#region 练习题
//定义一个载具类,速度,最大速度,可乘人数,司机和乘客等
//有上车,下车,行驶,车祸等方法,用载具类声明一个对象,并将若干人装载上车
class Person
{
public string name;
}
class Driver:Person
{
}
class Bus
{
public int driverNumber;
public int nowSpeed;
public int maxSpeed;
public int personNumber;
public Person[] persons;
public Bus(int nowSpeed, int maxSpeed, int personNumber)
{
this.nowSpeed = nowSpeed;
this.maxSpeed = maxSpeed;
this.personNumber = 0;
persons = new Person[personNumber];
}
public void Get(Person p)
{
personNumber++;
if (personNumber > 4)
{
Console.WriteLine("BUS满载!");
return;
}
persons[personNumber] = p;
Console.WriteLine("{0}上车了",p.name);
Console.WriteLine("车上有{0}个人,车速为{1}", personNumber, nowSpeed);
}
public void Out(Person p)
{
int j=0;
if (personNumber < 1)
{
Console.WriteLine("BUS已空!");
return;
}
else
{
personNumber--;
for (int i = 0; i < personNumber; i++)
{
if (persons[i] == p)
{
j=i;
break; ;
}
}
for (int i = j; i < personNumber; i++)
{
persons[i] = persons[i + 1];
}
Console.WriteLine("{0}下车了", p.name);
if (personNumber == 0)
{
Console.WriteLine("BUS停止");
}
else
{
Console.WriteLine("车上有{0}个人,车速为{1}", personNumber, nowSpeed);
}
}
}
public void Speed(int speed)
{
nowSpeed += speed;
if (nowSpeed > maxSpeed)
{
Console.WriteLine("当前车速为{0} 车速过快,发生车祸",nowSpeed);
return;
}
Console.WriteLine("车上有{0}个人,车速为{1}", personNumber, nowSpeed);
}
public void Slow(int slow)
{
nowSpeed -= slow;
if (nowSpeed == 0)
{
Console.WriteLine("BUS已停止");
return;
}
Console.WriteLine("车上有{0}个人,车速为{1}", personNumber, nowSpeed);
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("综合练习题");
Bus b = new Bus(100,120,5);
Person p = new Driver();
p.name = "司机";
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
Person p4 = new Person();
b.Get(p);
b.Speed(30);
}
}
}
using System;
namespace lesson17_多态_vob
{
#region 多态的概念
//多态按字面的意思就是"多种状态"
//让继承同一父类的子类们,在执行相同方法时有不同的表现(状态)
//主要目的
//同一父类的对象 执行相同行为(方法) 有不同的表现
//解决的问题
//让同一个对象有唯一行为的特征
#endregion
#region 解决的问题
class Father
{
public void SpeakName()
{
Console.WriteLine("Father的方法");
}
}
class Son : Father
{
public new void SpeakName()
{
Console.WriteLine("Son的方法");
}
}
#endregion
#region 多态的实现
//我们目前已经学过的多态
//编译时多态——函数重载,开始就写好的
//我们将学习的:
//运行时多态(vob,抽象函数,接口)
//我们今天学习vob
//v:virtual(虚函数)
//o:override(重写)
//b:base(父类)
class GameObject
{
public string name;
public GameObject(string name)
{
this.name = name;
}
//虚函数 可以被子类重写
public virtual void Atk()
{
Console.WriteLine("游戏对象进行攻击");
}
}
class Player : GameObject
{
public Player(string name) : base(name)
{
}
//重写虚函数
public override void Atk()
{
//base的作用
//代表父类 可以通过base来保留父类的行为
//base.Atk();
Console.WriteLine("玩家对象进行攻击");
}
}
class Monster : GameObject
{
public Monster(string name) : base(name)
{
}
public override void Atk()
{
base.Atk();
Console.WriteLine("怪物对象进行攻击");
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("多态_vob");
#region 解决的问题
Father f = new Son();
f.SpeakName();//Father的方法
(f as Son).SpeakName();//Son的方法
#endregion
#region 多态的使用
GameObject p = new Player("于双");
p.Atk();//玩家对象进行攻击
(p as Player).Atk();//玩家对象进行攻击
GameObject m = new Monster("小七");
m.Atk();//怪物对象进行攻击
(m as Monster).Atk();//怪物对象进行攻击
#endregion
}
}
//总结
//多态:让同一类型的对象,执行相同行为时有不同的表现
//解决的问题:让同一对象有唯一的行为特征
//vob:
//v:virtual 虚函数
//o:override 重写
//b:base 父类
//v和o一定是结合使用的 来实现多态
//b是否使用根据实际需求 保留父类行为
}
using System;
namespace lesson17_多态_vob练习题
{
#region 练习题1
//真的鸭子嘎嘎叫,木头鸭子吱吱叫,橡皮鸭子唧唧叫
class Duck
{
public string name;
public Duck(string name)
{
this.name = name;
}
public virtual void Speak()
{
Console.WriteLine();
}
}
class RealDuck:Duck
{
public RealDuck(string name) : base(name)
{
}
public override void Speak()
{
Console.WriteLine("{0}嘎嘎叫",name);
}
}
class WoodDuck : Duck
{
public WoodDuck(string name) : base(name)
{
}
public override void Speak()
{
Console.WriteLine("{0}吱吱叫",name);
}
}
class RubberDuck : Duck
{
public RubberDuck(string name) : base(name)
{
}
public override void Speak()
{
Console.WriteLine("{0}唧唧叫",name);
}
}
#endregion
#region 练习题2
//所有员工9点打卡
//但经理11点打卡,程序员不打卡
class Worker
{
public string name;
public Worker(string name)
{
this.name = name;
}
public virtual void Sign()
{
Console.WriteLine("9点{0}打卡",name);
}
}
class Manager : Worker
{
public Manager(string name) : base(name)
{
}
public override void Sign()
{
Console.WriteLine("11点{0}打卡", name);
}
}
class Programmer : Worker
{
public Programmer(string name) : base(name)
{
}
public override void Sign()
{
Console.WriteLine("{0}不打卡", name);
}
}
#endregion
#region 练习题3
//创建一个图形类,有求面积和周长两个方法
//创建矩形类,正方类,圆形类继承图形类
//实例化矩形、正方形、圆形对象求面积和周长
class Graph
{
public Graph()
{
}
public virtual void Area()
{
}
public virtual void Perimeter()
{
}
}
class Rectangle : Graph
{
public int Long;
public int Wide;
public Rectangle(int Long, int Wide)
{
this.Long = Long;
this.Wide = Wide;
}
public override void Area()
{
Console.WriteLine("矩形面积为{0}", Long * Wide);
}
public override void Perimeter()
{
Console.WriteLine("矩形周长为{0}",2*(Long+Wide));
}
}
class Square : Graph
{
public int Long;
public Square(int Long)
{
this.Long = Long;
}
public override void Area()
{
Console.WriteLine("正方形面积为{0}", Long * Long);
}
public override void Perimeter()
{
Console.WriteLine("正方形周长为{0}", 4*Long);
}
}
class Round : Graph
{
public int r;
static float PI = 3.14f;
public Round(int r)
{
this.r = r;
}
public override void Area()
{
Console.WriteLine("圆形面积为{0}",PI*r*r);
}
public override void Perimeter()
{
Console.WriteLine("圆形周长为{0}",2*PI*r);
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("vob练习题");
Duck d1 = new RealDuck("真鸭子");
Duck d2 = new WoodDuck("木头鸭子");
Duck d3 = new RubberDuck("橡皮鸭子");
d1.Speak();
d2.Speak();
d3.Speak();
Worker w1 = new Worker("员工");
Worker w2 = new Manager("经理");
Worker w3 = new Programmer("程序员");
w1.Sign();
w2.Sign();
w3.Sign();
Graph g1 = new Rectangle(2, 5);
Graph g2 = new Square(4);
Graph g3 = new Round(5);
g1.Area();
g1.Perimeter();
g2.Area();
g2.Perimeter();
g3.Area();
g3.Perimeter();
}
}
}
using System;
namespace lesson18_多态_抽象类和抽象方法
{
#region 抽象类
//概念
//被抽象关键字abstract修饰的类
//特点:
//1.不能被实例化的类
//2.可以包含抽象方法
//3.继承抽象类必须重写其抽象方法
abstract class Thing
{
//抽象类中 封装的所有知识点都可以在其中书写
public string name;
//可以在抽象类中写抽象函数
}
class Water : Thing
{
}
#endregion
#region 抽象函数
//又叫 纯虚方法
//用 abstract 关键字修饰的方法
//特点:
//1.只能在抽象类中申明
//2.没有方法体
//3.不能是私有的
//4.继承后必须实现 用override重写
abstract class Fruits
{
public string name;
//抽象方法 是一定不能有函数体的
public abstract void Bad();
public virtual void Test()
{
//可以选择是否写逻辑
}
}
class Apple : Fruits
{
public override void Bad()
{
}
//虚方法是可以由我们子类选择性来实现的
//抽象方法必须要实现
public override void Test()
{
base.Test();
}
}
class SuperApple : Apple
{
//虚方法和抽象方法 都可以被子类无限的 去重写
public override void Bad()
{
base.Bad();
}
public override void Test()
{
base.Test();
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("抽象类和抽象方法");
//抽象类不能被实例化
//Thing t = new Thing();
//但是 可以遵循里氏替换原则 用父类容器装子类
Thing t = new Water();
}
}
//总结
//抽象类 是被abstract修饰的类 不能被实例化 可以包含抽象方法
//抽象方法 没有方法体的纯虚方法 继承后必须去实现的方法
//注意:
//如何选择普通类还是抽象类
//不希望被实例化的对象,相对比较抽象的类可以使用的抽象类
//父类中的行为不太需要被实现的,只希望子类去定义具体的规则 可以选择 抽象类然后使用其中的抽象方法来定义规则
//作用:
//整体框架设计时 会使用
}
using System;
namespace lesson18_多态_抽象类和抽象方法练习题
{
#region 练习题1
//写一个动物抽象类,写3个子类
//人说话,狗叫,猫叫
abstract class Animal
{
public string name;
public Animal(string name)
{
this.name = name;
}
public abstract void Speak();
}
class Person:Animal
{
public Person(string name) : base(name)
{
}
public override void Speak()
{
Console.WriteLine("人说话");
}
}
class Dog : Animal
{
public Dog(string name) : base(name)
{
}
public override void Speak()
{
Console.WriteLine("{0}叫,嗷呜!嗷呜!",name);
}
}
class Cat : Animal
{
public Cat(string name) : base(name)
{
}
public override void Speak()
{
Console.WriteLine("{0}叫,喵喵喵",name);
}
}
#endregion
#region 练习题2
//创建一个图形类,有求面积和周长两个方法
//创建矩形类,正方形类,圆形类继承图形类
//实例化矩形,正方形,圆形对象求面积和周长
abstract class Graph
{
public abstract void Area();
public abstract void Perimeter();
}
class Rectangle : Graph
{
public int Long;
public int Wide;
public Rectangle(int Long, int Wide)
{
this.Long = Long;
this.Wide = Wide;
}
public override void Area()
{
Console.WriteLine("矩形面积为{0}", Long * Wide);
}
public override void Perimeter()
{
Console.WriteLine("矩形周长为{0}", 2 * (Long + Wide));
}
}
class Square : Graph
{
public int Long;
public Square(int Long)
{
this.Long = Long;
}
public override void Area()
{
Console.WriteLine("正方形面积为{0}", Long * Long);
}
public override void Perimeter()
{
Console.WriteLine("正方形周长为{0}", 4 * Long);
}
}
class Round : Graph
{
public int r;
static float PI = 3.14f;
public Round(int r)
{
this.r = r;
}
public override void Area()
{
Console.WriteLine("圆形面积为{0}", PI * r * r);
}
public override void Perimeter()
{
Console.WriteLine("圆形周长为{0}", 2 * PI * r);
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("象类和抽象方法练习题");
#region 练习题1
Animal a1 = new Person("于双");
Animal a2 = new Dog("哈士奇");
Animal a3 = new Cat("布偶");
a1.Speak();
a2.Speak();
a3.Speak();
#endregion
#region 练习题2
Graph g1 = new Rectangle(4, 3);
Graph g2 = new Square(4);
Graph g3 = new Round(4);
g1.Area();
g1.Perimeter();
g2.Area();
g2.Perimeter();
g3.Area();
g3.Perimeter();
#endregion
}
}
}
using System;
namespace lesson19_多态_接口
{
#region 接口的概念
//接口是行为的抽象规范
//它也是一种自定义类型
//关键字:interface
//籍人口申明的规范
//1.不包含成员变量
//2.只包含方法,属性,索引器,事件
//3.成员不能被实现
//4.成员可以不用写访问修饰符,不能是私有的
//5.接口不能继承类,但是可以继承另一个接口
//接口的使用规范
//1.类可以继承多个接口
//2.类继承接口后,必须实现接口中所有成员
//特点
//1.它和类的申明相似
//2.接口是用来继承的
//3.接口不能被实例化,但是可以作为容器存储对象
#endregion
#region 接口的申明
//接口关键字:interface
//语法:
// interface 接口名
// {
// }
//一句话记忆:接口是抽象行为的"基类"
//接口命名规范 帕斯卡命名法前面加个I
interface IFly
{
//默认public 不可以写pravite
void Fly();
//属性
string Name
{
get;
set;
}
//索引器
int this[int index]
{
get;
set;
}
//事件
event Action doSomething;
}
#endregion
#region 接口的使用
//接口用来继承
class Animal
{
}
//1.类可以继承1个类 n个接口
//2.继承了接口后 必须实现其中的内容 并且必须加public
class Person : Animal, IFly
{
//3.实现的接口函数 可以加v再在子类中重写
public virtual void Fly()
{
}
public string Name
{
get;
set;
}
public int this[int index]
{
get
{
return 0;
}
set
{
}
}
public event Action doSomething;
}
#endregion
#region 接口可以继承接口
//接口继承接口时 不需要去实现
//待类继承接口后 类自己去实现所有内容
interface IWalk
{
void Walk();
}
interface IMove : IFly, IWalk
{
}
class Test : IMove
{
public int this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public event Action doSomething;
public void Fly()
{
throw new NotImplementedException();
}
public void Walk()
{
throw new NotImplementedException();
}
}
#endregion
#region 显示实现接口
//当一个类继承两个接口
//但是接口中存在着同名方法时
//注意:显示实现接口时 不能写访问修饰符
interface IAtk
{
void Atk();
}
interface ISuperAtk
{
void Atk();
}
class Player : IAtk, ISuperAtk
{
//显示实现接口 就是用 接口名.行为名 去实现
void ISuperAtk.Atk()
{
throw new NotImplementedException();
}
void IAtk.Atk()
{
throw new NotImplementedException();
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("接口");
//4.接口也遵循里氏替换原则
//IFly f = new IFly(); 接口不能被实例化
IFly f = new Person();
IMove im = new Test();
IFly ifly = new Test();
IWalk iw = new Test();
IAtk ia = new Player();
ISuperAtk isa= new Player();
ia.Atk();
isa.Atk();
Person p = new Person();
(p as IAtk).Atk();
(p as ISuperAtk).Atk();
}
}
//总结
//继承类:是对象间的继承,包括特征行为等等
//继承接口:是行为间的继承,继承接口的行为规范,按照规范去实现内容
//由于接口也是遵循里氏替换原则,所以可以用接口容器装对象
//那么就可以实现 装载各种毫无关系但是却相同行为的对象
//注意:
//1.接口只包含 成员方法、属性、索引器、事件、、并且都不实现,都没有访问修饰符
//2.可以继承多个接口,但是只能继承一个类
//3.接口可以继承接口,相当于在进行行为合并,待子类继承时再去实现具体的行为
//4.接口可以被显示实现 主要用于实现不同接口中的同名函数的不同表现
//5.实现的接口方法 可以加 virtual 关键字 之后子类 再重写
}
using System;
namespace lesson19_多态_接口练习题
{
#region 练习题1
//人、汽车、房子都需要登记
//人需要到派出所登记,汽车需要去车管所等级,房子需要去房管局登记
//使用接口实现登记方法
interface IRegister
{
void Register();
}
class Person : IRegister
{
public void Register()
{
Console.WriteLine("人登记");
}
}
class Car : IRegister
{
public void Register()
{
Console.WriteLine("车登记");
}
}
class House : IRegister
{
public void Register()
{
Console.WriteLine("房子登记");
}
}
#endregion
#region 练习题2
//麻雀、鸵鸟、企鹅、鹦鹉、直升机、天鹅
//直升机和部分鸟能飞
//鸵鸟和企鹅不能飞
//企鹅和天鹅能游泳
//除了直升机,其它都能走
//请用面向对象相关知识实现
interface IFly
{
void Fly();
}
interface ISwimming
{
void Swimming();
}
interface IWalk
{
void Walk();
}
class Thing
{
public string name;
public Thing(string name)
{
this.name=name;
}
}
class CanFly : Thing, IFly
{
public CanFly(string name) : base(name)
{
}
public void Fly()
{
Console.WriteLine("{0}能飞", name);
}
}
class CanSwimming : Thing, ISwimming
{
public CanSwimming(string name) : base(name)
{
}
public void Swimming()
{
Console.WriteLine("{0}能游泳", name);
}
}
class CanWalk : Thing, IWalk
{
public CanWalk(string name) : base(name)
{
}
public void Walk()
{
Console.WriteLine("{0}能走路", name);
}
}
class Both1 : Thing,IFly,ISwimming
{
public Both1(string name) : base(name)
{
}
public void Fly()
{
Console.WriteLine("{0}既能飞", name);
}
public void Swimming()
{
Console.WriteLine("{0}还能游泳", name);
}
}
class Both2 : Thing, IFly, IWalk
{
public Both2(string name) : base(name)
{
}
public void Fly()
{
Console.WriteLine("{0}既能飞", name);
}
public void Walk()
{
Console.WriteLine("{0}还能走路", name);
}
}
class Both3 : Thing, ISwimming, IWalk
{
public Both3(string name) : base(name)
{
}
public void Swimming()
{
Console.WriteLine("{0}既能游泳", name);
}
public void Walk()
{
Console.WriteLine("{0}还能走路", name);
}
}
class All : Thing, IFly, ISwimming, IWalk
{
public All(string name) : base(name)
{
}
public void Fly()
{
Console.WriteLine("{0}既能飞", name);
}
public void Swimming()
{
Console.WriteLine("{0}还能游泳", name);
}
public void Walk()
{
Console.WriteLine("{0}还能走路", name);
}
}
#endregion
#region 练习题3
//多态来模拟移动硬盘、U盘、MP3插到电脑上读取数据
//移动硬盘与U盘都属于存储设备
//MP3属于播放设备
//但他们都能插在电脑上传输数据
//电脑提供了一个USB接口
//请实现电脑的传输数据的功能
interface IUsb
{
void ReadDate();
}
class Hdd:IUsb
{
public string name;
public Hdd(string name)
{
this.name=name;
}
public void ReadDate()
{
Console.WriteLine("{0}传输数据",name);
}
}
class Usb : IUsb
{
public string name;
public Usb(string name)
{
this.name = name;
}
public void ReadDate()
{
Console.WriteLine("{0}传输数据", name);
}
}
class Mp3 : IUsb
{
public string name;
public Mp3(string name)
{
this.name = name;
}
public void ReadDate()
{
Console.WriteLine("{0}传输数据", name);
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("接口练习题");
#region 练习题1
IRegister r1 = new Person();
IRegister r2 = new Car();
IRegister r3 = new House();
r1.Register();
r2.Register();
r3.Register();
#endregion
#region 练习题2
Both2 t1 = new Both2("麻雀");
t1.Fly();
t1.Walk();
IWalk t2 = new CanWalk("鸵鸟");
t2.Walk();
Both3 t3 = new Both3("企鹅");
t3.Swimming();
t3.Walk();
Both2 t4 = new Both2("鹦鹉");
t4.Fly();
t4.Walk();
IFly t5 = new CanFly("直升机");
t5.Fly();
All t6 = new All("天鹅");
t6.Fly();
t6.Swimming();
t6.Walk();
#endregion
#region 练习题3
IUsb i1 = new Hdd("移动硬盘");
IUsb i2 = new Hdd("U盘");
IUsb i3 = new Hdd("MP3");
i1.ReadDate();
i2.ReadDate();
i3.ReadDate();
#endregion
}
}
}
using System;
namespace lesson20_多态_密封方法
{
#region 密封类知识回顾
//密封类
//用sealed修饰的类
//让类不再能被继承"结扎"
#endregion
#region 密封方法的基本概念
//用密封关键字sealed 修饰的重写函数
//作用:让虚方法或者抽象方法之后不能再被重写
//特点:和override一起出现
#endregion
#region 实例
abstract class Animal
{
public string name;
public abstract void Eat();
public virtual void Speak()
{
Console.WriteLine("叫");
}
}
class Person : Animal
{
public sealed override void Eat()
{
}
public override void Speak()
{
}
}
class WhitePerson : Person
{
//不能重写密封方法
/*public override void Eat()
{
}*/
public override void Speak()
{
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("密封方法");
}
}
//总结
//密封方法 可以让虚方法和抽象方法不能再被子类重写
//特点:一定是和 override 一起出现
}
//引用MyGame命名空间
//using MyGame;
using System;
#region 命名空间的基本概念
//概念
//命名空间是用来组织和重用代码的
//作用
//就像是一个工具包,类就像是一件一件的工具,都是申明在命名空间中的
#endregion
#region 命名空间的使用
//基本语法
// namespace 命名空间名
// {
// 类
// 类
// }
namespace MyGame
{
class GameObject
{
}
}
namespace MyGame
{
class Player : GameObject
{
}
}
#endregion
#region 不同命名空间中允许有同名类
namespace MyGame2
{
//在不同的命名空间中可以有同名类
class GameObject
{
}
}
#endregion
#region 命名空间可以包裹命名空间
namespace MyGame
{
namespace UI
{
class Image
{
}
}
namespace Game
{
class Image
{
}
}
}
#endregion
#region 关于修饰类的访问修饰符
// public——命名空间中的类 默认为publi
// internal——只能在该程序集中使用
// abstact——抽象类
// sealed——密封类
// partial——分部类
#endregion
namespace lesson21_面向对象相关_命名空间
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("命名空间");
#region 不同命名空间中相互使用 需要引用命名空间或指明出处
MyGame.GameObject g = new MyGame.GameObject();
MyGame2.GameObject g2 = new MyGame2.GameObject();
MyGame.UI.Image img = new MyGame.UI.Image();
MyGame.Game.Image img2 = new MyGame.Game.Image();
#endregion
}
}
}
//总结
//1.命名空间是个工具包 用来管理类的
//2.不同命名空间中 可以有同名类
//3.不同命名空间中相互使用 需要 using 引用命名空间 或者 指明出处
//4.命名空间可以包裹命名空间
using System;
#region 练习题1
//请说明关键字using有什么作用
//using 用来引用命名空间
#endregion
#region 练习题2
//有两个命名空间,UI(用户界面)和Graph(图表)
//两个命名空间中都有一个Image类
//请在主函数中实例化两个不同命名空间中的Image对象
namespace UI
{
class Image
{
}
}
namespace Graph
{
class Image
{
}
}
#endregion
namespace lesson21_面向对象相关_命名空间练习题
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("命名空间练习题");
UI.Image i1 = new UI.Image();
Graph.Image i2 = new Graph.Image();
}
}
}
using System;
namespace lesson22_面对对象相关_万物之父中的方法
{
class Test
{
public int i = 1;
public Test2 t2 = new Test2();
public Test Clone()
{
return MemberwiseClone() as Test;
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override string ToString()
{
return "申明的Test类";
}
}
class Test2
{
public int i = 2;
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("万物之父中的方法");
#region 万物之父知识回顾
//万物之父 object
//所有类型的基类 是一个引用类型
//可以利用里氏替换原则装载一切对象
//存在装箱拆箱
#endregion
#region object中的静态方法
//静态方法 Equals 判断两个对象是否相等
//最终的判断全,交给左侧对象的Equals方法
//不管值类型引用类型都会按照左侧对象Equals方法的规则来进行比较
Console.WriteLine(object.Equals(1, 1));//True
//Test t = new Test();
//Test t2 = new Test();
//Console.WriteLine(object.Equals(t, t2));//False
//静态方法 ReferenceEquals
//比较两个对象是否是相同的引用,主要是用来比较引用类型的对象
//值类型对象返回值始终是false
Console.WriteLine(object.ReferenceEquals(1, 1));//False
//Console.WriteLine(object.ReferenceEquals(t, t2));//False
#endregion
#region object中的成员方法
//普通方法GetType
//该方法在反射相关知识点中是非常重要的方法,之后我们会具体的讲解这里返回的Type类型
//该方法的主要作用就是获取对象运行时的类型Type
//通过Type结合反射相关知识点可以做很多关于对象的操作
Test t = new Test();
Type type = t.GetType();
//普通方法MemberwiseClone
//该方法用于获取对象的浅拷贝对象,口语化的意思就是会返回一个新的对象
//但是新对象中的引用变量会和老对象中一致
Test t2 = t.Clone();
Console.WriteLine("克隆对象后");
Console.WriteLine("t.i=" + t.i);
Console.WriteLine("t.t2.i=" + t.t2.i);
Console.WriteLine("t2.i=" + t2.i);
Console.WriteLine("t2.t2.i=" + t2.t2.i);
t2.i = 20;
t2.t2.i = 21;
Console.WriteLine("改变克隆体信息后");
Console.WriteLine("t.i=" + t.i);
Console.WriteLine("t.t2.i=" + t.t2.i);
Console.WriteLine("t2.i=" + t2.i);
Console.WriteLine("t2.t2.i=" + t2.t2.i);
#endregion
#region object中的虚方法
//虚方法 Equals
//默认实现还是比较两者是否为同一个引用,即相当ReferenceEquals
//但是微软在所有值类型的基类 System。ValueType中重写了该方法,用来比较值相等
//我们也可以重写该方法,定义自己的比较相等的规则
//虚方法 GetHashCode
//该方法是获取对象的哈希码
//(一种通过算法算出的,表示对象的唯一编码,不同对象哈希码可能一样,具体值根据哈希算法决定)
//我们可以通过重写该函数来自己定义对象的哈希码算法,正常情况下,我们使用的极少,基本不用
//虚方法 ToString
//该方法用于返回当前对象代表的字符串,我们可以重写它定义我们自己的对象转字符串规则
//该方法非常常用,当我们调用打印方法时,默认使用的就是对象的ToString方法后打印出来的内容
Console.WriteLine(t);
#endregion
}
}
//总结
//1.虚方法 toString 自定字符串转换规则
//2.成员方法 GetType 反射相关
//3.成员方法 MemberwiseClone 浅拷贝
//4.虚方法 Equals 自定义判断相等的规则
}
using System;
namespace lesson22_面对对象相关_万物之父中的方法练习题
{
#region 练习题1
//有一个玩家类,有姓名、血量、攻击力、防御力、闪避率等特征
//请在控制台打印出 "玩家xx,血量xx,攻击力xx,防御力xx,闪避率xx"
//xx为具体内容
class Player
{
public string name;
public int hp;
public int atk;
public int def;
public float evd;
public Player(string name, int hp, int atk, int def, float evd)
{
this.name = name;
this.hp = hp;
this.atk = atk;
this.def = def;
this.evd = evd;
}
public void Speak()
{
Console.WriteLine("玩家{0} 血量为{1} 攻击力为{2} 防御力为{3} 闪避率为{4}",name,hp,atk,def,evd);
}
}
#endregion
#region 练习题2
//一个Monster类的引用对象A,Monster类有 攻击力、防御力、血量、技能ID等属性
//我想复制一个和A对象一模一样的B对象,并且改变了B的属性,A不会受到影响
//请问如何实现
class Monster
{
public int hp;
public int atk;
public int def;
public int id;
public Monster(int hp,int atk,int def,int id)
{
this.hp = hp;
this.atk = atk;
this.def = def;
this.id = id;
}
public Monster Clone()
{
return MemberwiseClone() as Monster;
}
public override string ToString()
{
return string.Format("血量为{0} 攻击力为{1} 防御力为{2} 技能ID为{3}",hp , atk, def, id);
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("万物之父中的方法练习题");
Player p = new Player("小七", 100, 10, 5, 0.2f);
p.Speak();
Monster m = new Monster(100, 20, 10, 1);
Monster m2 = m.Clone();
m2.atk= 30;
m2.id = 2;
Console.WriteLine(m);
Console.WriteLine(m2);
}
}
}
using System;
namespace lesson23_面向对象相关_string
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("string");
#region 字符串指定位置获取
//字符串本质是char数组
string str = "于双";
Console.WriteLine(str[0]);//于
//转为char数组
char[] chars = str.ToCharArray();
Console.WriteLine(chars[1]);//双
for (int i = 0; i < str.Length; i++)
{
Console.WriteLine(str[i]);
}
//于
//双
#endregion
#region 字符串拼接
str = string.Format("{0}{1}",1,333);
Console.WriteLine(str);//1333
#endregion
#region 正向查找字符位置
str = "我是于双!";
int index=str.IndexOf("于");
Console.WriteLine(index);//2
index = str.IndexOf("黄");
Console.WriteLine(index);//1
#endregion
#region 反向查找指定字符串位置
str = "我是于双于双";
index = str.LastIndexOf("于双");
Console.WriteLine(index);//4
#endregion
#region 移除指定位置后的字符
str = "我是于双";
str.Remove(3);
Console.WriteLine(str);//我是于双
str = str.Remove(3);
Console.WriteLine(str);//我是于
//执行两个参数进行移除
//参数1 开始位置
//参数2 字符个数
str = "我是于双";
str = str.Remove(1, 1);
Console.WriteLine(str);//我于双
#endregion
#region 替换指定字符串
str = "我是于双于双";
str.Replace("于双", "老炮儿");//我是于双于双
Console.WriteLine(str);
str=str.Replace("于双", "老炮儿");
Console.WriteLine(str);//我是老炮儿老炮儿
#endregion
#region 大小写转换
str = "abc";
str.ToUpper();
Console.WriteLine(str);//abc
str=str.ToUpper();
Console.WriteLine(str);//ABC
str = str.ToLower();
Console.WriteLine(str);//abc
#endregion
#region 字符串截取
str = "我是于双于双";
//截取从指定位置开始之后的字符串
str.Substring(2);
Console.WriteLine(str);//我是于双于双
str = str.Substring(2);
Console.WriteLine(str);//于双于双
//参数1 开始位置
//参数2 指定个数
//不会自动的帮助你判断是否越界 你需要自己去判断
str = "我是于双于双";
str = str.Substring(2, 3);
Console.WriteLine(str);//于双于
#endregion
#region 字符串切割
str = "1,2,3,4,5,6,7,8,9";
string[] strs = str.Split(',');//以‘’里的为界限分割
for (int i = 0; i < strs.Length; i++)
{
Console.WriteLine(strs[i]);
}
#endregion
}
}
}
using System;
namespace lesson23_面向对象相关_string练习题
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("string练习题");
#region 练习题1
//请写出string中提供的截取和替换对应的函数名
//截取
string str;
str = "我是于双于双";
//截取从指定位置开始之后的字符串
str.Substring(2);
Console.WriteLine(str);//我是于双于双
str = str.Substring(2);
Console.WriteLine(str);//于双于双
//参数1 开始位置
//参数2 指定个数
//不会自动的帮助你判断是否越界 你需要自己去判断
str = "我是于双于双";
str = str.Substring(2, 3);
Console.WriteLine(str);//于双于
//替换
str = "我是于双于双";
str.Replace("于双", "老炮儿");//我是于双于双
Console.WriteLine(str);
str = str.Replace("于双", "老炮儿");
Console.WriteLine(str);//我是老炮儿老炮儿
#endregion
#region 练习题2
//请将字符串 1|2|3|4|5|6|7
//变为 2|3|4|5|6|7|8
//并输出(使用字符串切割的方法)
str = "1 | 2 | 3 | 4 | 5 | 6 | 7";
string[] strs = str.Split('|');
str = "";
for (int i = 0; i < strs.Length; i++)
{
str += int.Parse(strs[i]) + 1;
if (i != strs.Length - 1)
{
str += "|";
}
}
Console.WriteLine(str);
#endregion
#region 练习题3
//String 和 string 、Int32 和 int 、Int16 和 short 、Int64 和 long 他们的区别是什么?
//别名,本质是一家
#endregion
#region 练习题4
//string str=null;
//str="123";
//string str2=str;
//str2="321";
//str2+="123";
//请问,上面这段代码,分配了多少个新的堆空间
//3个新的堆空间 “123”,“321”,“321123”
#endregion
#region 练习题5
//编写一个函数,将输入的字符串反转。不要使用中间商,你必须原地修改输入数组。交换过程中不使用额外空间
//比如:输入{‘h’,‘e’,‘l’,‘l’,‘o’}
//输出 {‘o’,‘l’,‘l’,‘e’,‘h’}
str = "'h','e','l','l','o'";
for (int i = str.Length-1; i >= 0; i--)
{
Console.Write(str[i]);
}
//可使用递归 return Console.Write(str[str.Length-1]);
#endregion
}
}
}
using System;
using System.Text;
namespace lesson24_面向对象相关_StringBuilder
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("StringBuilder");
#region string 知识回顾
//string 是特殊的引用
//每次重新赋值或者拼接时会分配新的内存空间
//如果一个字符串经常改变会非常浪费空间
#endregion
#region StringBuilder
//C#提供的一个用于处理字符串的公共类
//主要解决的问题是:
//修改字符串而不创建新的对象,需要频繁修改和拼接的字符串可以使用它,可以提升性能
//使用前 需要引用命名空间
#region 初始化 直接指明内容
StringBuilder str = new StringBuilder("123123123");
Console.WriteLine(str);//123123123
#endregion
#region 容量
//StringBuilder 存在一个容量的问题,每次往里面增加时 会自动扩容
//获得容量
Console.WriteLine(str.Capacity);//16
//获得字符长度
Console.WriteLine(str.Length);//9
#endregion
#region 增删查改替换
//增
str.Append("4444");
Console.WriteLine(str);//1231231234444
Console.WriteLine(str.Length);//13
Console.WriteLine(str.Capacity);//16
str.AppendFormat("{0}{1}", 100, 999);
Console.WriteLine(str);//1231231234444100999
Console.WriteLine(str.Length);//19
Console.WriteLine(str.Capacity);//32
//插入
str.Insert(0, "于双");
Console.WriteLine(str);//于双1231231234444100999
//删
str.Remove(0, 10);//删除从0索引开始的10个数
Console.WriteLine(str);//34444100999
//清空
/*str.Clear();
Console.WriteLine(str);*/
//查
Console.WriteLine(str[0]);//3
//改
str[0] = 'A';
Console.WriteLine(str);//A4444100999
//替换
str.Replace("1", "于");
Console.WriteLine(str);//A4444于00999
//重新赋值 StringBuilder
str.Clear();
str.Append("123123");
Console.WriteLine(str);//123123
//判断 StringBuilder 是否和某一个字符串相等
if (str.Equals("123123"))
{
Console.WriteLine("相等");//相等
}
#endregion
#endregion
}
}
}
using System;
namespace lesson24_面向对象相关_StringBuilder练习题
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("StringBuilder练习题");
#region 练习题1
//请描述 string 和 StringBuilder 的区别
//1.string相对stringbuilder 更容易产生垃圾 每次修改拼接都会产生垃圾
//2.string相对stringbuilder 更加灵活 因为它提供了更多的方法供使用
//如何选择他们两
//需要频繁修改拼接的字符串可以使用stringbuilder
//需要使用string独特的一些方法来处理一些特殊逻辑时可以使用string
#endregion
#region 练习题2
//如何优化内存
//内存优化 从两个方面去解答
//1.如何节约内存
//2.如何尽量少的GC(垃圾回收)
//少new对象 少产生垃圾
//合理使用static
//合理使用string和stringbuilder
#endregion
}
}
}
using System;
namespace lesson25_面向对象相关_结构体和类的区别
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("结构体和类的区别");
#region 区别概述
//结构体和类的最大的区别是在存储空间上的,因为结构体是值,类是引用
//因此他们的存储位置一个在栈上,一个在堆上
//通过之前知识点的学习,我相信你能够从此处看出他们在使用的区别——值和引用对象在赋值时的区别
//结构体和类在使用上很类似,结构体甚至可以用面向对象的思想来形容一类对象
//结构体具备着面向对象思想中封装的特性,但他不具备继承和多态的特性,因此大大减少了它的使用频率
//由于结构体不具备继承的特性,所以它不能够使用protected保护访问修饰符
#endregion
#region 细节区别
//1.结构体是值类型,类是引用类型
//2.结构体存在栈中,类存在堆中
//3.结构体成员不能使用 protected 访问修饰符,而类可以
//4.结构体成员变量申明不能指定初始值,而类可以
//5.结构体不能申明无参的构造函数,而类可以
//6.结构体申明有参构造函数后,无参构造不会被顶掉
//7.结构体不能申明析构函数,而类可以
//8.结构体不能被继承,而类可以
//9.结构体需要在构造函数中初始化所有成员变量,而类随意
//10.结构体不能被静态 sratic 修饰 (不存在静态结构体),而类可以
//11.结构体不能在自己内部申明和自己一样的结构体变量,而类可以
#endregion
#region 结构体的特别之处
//结构体可以继承 接口 因为接口是行为的抽象
#endregion
#region 如何选择结构体和类
//1.想要使用继承和多态时,直接淘汰结构体,比如玩家、怪物等等
//2.对象是数据集合时,优先考虑结构体,比如位置、坐标等等
//3.从值类型和引用类型赋值时的区别上去考虑,比如经常被赋值传递的对象
//并且改变赋值对象,原对象不想跟着变化时,就用结构体,比如坐标、向量、旋转等等
#endregion
}
}
}
using System;
namespace lesson26_面向对象相关_抽象类和接口的区别
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("抽象类和接口的区别");
#region 知识回顾
//抽象类和抽象方法
// abstract 修饰的类和方法
//抽象类不能实例化
//抽象方法只能在抽象类中申明 是个纯虚方法 必须在子类中实现
//接口
// interface 自定义类型
//是行为的抽象
//不包含成员变量
//仅包含方法、属性、索引器,成员都不能实现,建议不写访问修饰符,默认public
#endregion
#region 相同点
//1.都可以被继承
//2.都不能直接实例化
//3.都可以包含方法申明
//4.子类必须实现未实现的方法
//5.都遵循里氏替换原则
#endregion
#region 区别
//1.抽象类中可以有构造函数;接口中不能
//2.抽象类只能被单一继承;接口可以被继承多个
//3.抽象类中可以有成员变量;接口中不能
//4.抽象类中可以申明成员方法,虚方法,抽象方法,静态方法;接口中只能申明没有实现的抽象方法
//5.抽象类方法可以使用访问修饰符;接口中建议不写,默认public
#endregion
#region 如何选择抽象类和接口
//表示对象的用抽象类,表示行为拓展的用接口
//不同对象拥有的共同行为,我们往往可以使用接口来实现
//举个栗子:(故意的,哈哈哈!)
//动物是一类对象,我们自然会选择抽象类;而飞翔是一个行为,我们自然会选择接口
#endregion
}
}
}
using System;
namespace lesson27_面向对象七大原则
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("面向对象七大原则");
#region 单一职责原则
//SRP(Single Responsibility Principle)
//类被修改的几率很大,因此应该专注于单一的功能。
//如果把多个功能放在同一个类中,功能之间就形成了关联,改变其中一个功能,有可能中止另一个功能。
//举例: 假设程序、策划、美术三个工种是三个类,他们应该各司其职,在程序世界中只应该做自己应该做的事情。
#endregion
#region 开闭原则
//OCP(Open - Closed Principle)对拓展开发,对修改关闭
//拓展开放:模块的行为可以被拓展从而满足新的需求
//修改关闭:不允许修改模块的源代码(或者尽量使修改最小化)
//举例: 继承就是最典型的开闭原则的体现,可以通过添加新的子类和重写父类的方法来实现
#endregion
#region 里氏替换原则
//LSP(Liskov Substitution Principle)任何父类出现的地方,子类都可以替代
//举例:用父类容器装载子类对象,因为子类对象包含了父类的所有内容
#endregion
#region 依赖倒转原则
//DIP(Dependence Inversion Principle)要依赖于抽象,不要依赖于具体的实现
#endregion
#region 迪米特原则
//LoP(Law of Demeter)又称最少知识原则
//一个对象应当对其它对象尽可能少的了解(不要和陌生人说话)
//举例: 一个对象中的成员,要尽可能少的直接和其它类建立关系。目的是降低耦合性
#endregion
#region 接口分离原则
//ISP(Interface Segregation Principle)不应该强迫别人依赖他们不需要使用的方法
//一个接口不需要提供太多的行为,一个接口应该尽量只提供一个对外的功能,让别人去选择需要实现什么样的行为,而不是把所有的行为都封装到一个接口当中
//举例:飞行接口、走路接口、跑步接口等等虽然都是移动的行为但是我们应该把他们分为一个一个单独的接口,让别人去选择使用
#endregion
#region 合成复用原则
//CRP(Composite Reuse Principle)
//尽量使用对象组合,而不是继承来达到复用的目的继承关系是强耦合,组合关系是低耦合
//举例:脸应该是眼镜、鼻子、嘴巴、耳朵的组合,而不是依次的继承角色和装备也应该是组合,而不是继承
//注意:不能盲目的使用合成复用原则,要在遵循迪米特原则的前提下
#endregion
#region 总结
//单一职责原则: 一个类只处理自己应该处理的内容,不应该啥都写在一起
//开闭原则:对拓展开放,对修改封闭。新加功能尽量是加处理而不是改代码
//里氏替换原则:任何地方子类都能替代父类,父类容器装子类
//依赖倒转原则:不要依赖具体的实现,要依赖抽象(接口)
//迪米特法则: 一个类要尽量减少对别的类的了解,尽量少用别的类和自己关联
//接口隔离原则:一个接口一个行为,不要一个接口n个行为
//合成复用原则:除非设计上需要继承,否则尽量用组合复用的形式
#endregion
}
}
}