类的复习
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
-
类的概述
程序把数据和行为组织成逻辑上相关的数据项和函数的集合,称之为类. 类是一种活动的数据结构.数据项成员是存储与类或类的实例相关的的数据.函数成员,它是执行代码.
数据成员存储 函数成员执行代码 |
√字段 √方法 □运算符 □常量 √属性 □索引 √ 构造函数 □事件 √析构函数 |
(打√表示本篇笔记里会写到的要点,打□ 表示暂时未完成的复习要点) |
说明 类是逻辑相关的数据和函数的封装,通常代表真实世界中的或概念上的事物 |
-
类的声明
类的声明定义新类的特征和成员.但它并不创建类的实例,但创建了用于创建实例的模板,类的声明包括以下内容:类的名称、类的成员、类的特征
class MyExcellentClass { private int myField; //声明一个字段,该字段的访问修饰符为private私有成员,因此在类的内部无法访问到该类的这个字段,默认初始化的值是0; public int MyField //声明一个属性,以使得可以在类的外部设置和读取私有字段myField的值. { set { myField = value; } get { return myField; } } public void Fuction() //声明一个方法 { Console.WriteLine("这是我的行为动作,哈哈"); } //声明一个无参数构造方法 //用来初始化类的实例状态,当创建对象就是通过调用构造方法创建的, // 此处无参数构造方法可以省略, 在程序员没有声明构造方法的时候,程序会有一个默认的无参数且方法体为空的构造方法,若程序员声明了构造方法,便不存在默认的无参数,方法体为空的构造方法,必须手动声明才会有.构造方法可以重载 public MyExcellentClass() { } //析构函数,执行在类的实例被销毁之前需要的需要的清理或释放非托管资源的行为. // 每个类只有一个析构函数,析构函数不能带参数,无访问修饰符,只对类的实例又作用,因c#,Java有GC垃圾回收站,会自动回收托管资源对象,对于非托管资源对象,一般在using语句中创建对象using会释放非托管资源对象,所以析构函数在c#中运用较少 ~MyExcellentClass() { } }
-
成员讲解
- 字段
字段是隶隶属于累的变量,用来保存与类或类的实例相关的数据,字段可以是任何类型(预定义类型或用户类型都可以),和所有变量一样,可以被写入或读取.声明一个字段的最简单语句: Type Identifier 如: int myField;.
2. 属性
属性是代表类的实例或类中的一个数据项的成员,使用属性看起来非常像写入或读取一个字段.
与字段的相同点:都是类的成员.有类型.可以被赋值和读取.
与字段的不同点:它不为数据存储分配内存.它执行代码.属性是指定的一组匹配的,称为访问器的方法,set访问器用于属性赋值,get访问器用于从属性获取值.
举例见代码:
class Program { static void Main(string[] args) { Test test1 = new Test();//new的时候创建对象,并给该对象分配存储数据项的内存 test1.SetFloor(14);//通过调用方法设置私有字段的值 test1.Break(); Console.WriteLine("我有{0}层", test1.GetFloor());//通过调用方法获取私有字段的值 Test test2 = new Test(); test2.Floor = 10;//通过访问属性来设置私有字段的值 test2.Break(); Console.WriteLine("我有{0}层",test2.Floor);//通过访问属性来获取私有字段的值 Console.ReadKey(); } } class Test { private int floor;//字段就是表示类的一些特征 public void Break() { //方法可以看成是类的能力,行为或动作 if (floor > 10) { Console.WriteLine("我就要倒塌了"); } else { Console.WriteLine("我还ok"); } } public void SetFloor(int value) {//为了能在类的外部访问到pirvate私有字段floor,有了给字段赋值的方法 floor = value; } public int GetFloor() //为了能在类的外部获得floor的值,设置取值方法 { return floor; } //为了方便获取或是对私有字段赋值,就有了属性,属性就是将以上两个方法的SetFloor和GetFloor合并在一起.来代替上述两个方法 public int Floor { set { floor = value; } get { return floor; } } ~Test()//析构函数用来回收资源 { Console.WriteLine("我结束了"); Console.ReadKey(); } }
我们通过反编译发现,Test.Floor属性内部实质就是:
public void SetFloor(int value) { floor = value; } public int GetFloor() { return floor; }
所以
set访问器总是:一个单独的、隐式的值参;名称为value,与属性的类型相同,一个返回类型为void.
get访问器总是:没有参数;一个与属性类型相同的返回类型.
结论:惯例是在类中将字段声明为private以封装为private以封装一个字段,并声明一个public属性以提供受控的对字段的访问.和属性相关的字段常被称为后后备字段或后备存储.
之所以选择用属性,而不是直接定义一个public字段.原因是:属性允许处理输入和输出,而公共字段不行.比如
private int myFiled; public int MyFiled { set{myFiled=value>100?100:0;}//MyFiled属性只接受非负数 get{ return myFiled;} }
另外,只有get访问器的属性称为只读属性.只读属性是一种安全行为,把一项数据从类或类的实例中传出,而不允许太多的访问.
只有set访问器的属性称为只写属性,只写属性是把一项数据从类的外部传入类而不允许太多访问的安全方法.
两个访问器至少有一个必须定义,否则编译器会产生一条错误.
自动实现属性
前提:(1)不声明后备字段----编译器根据属性的类型分配存储。
(2)不能提供访问器的方法体---它们必须被简单地声明为分号。get担当简单的内存读,set担当简答的写.
(3)因此必须同时提供读写访问器。
3. 构造方法
构造函数用于初始化类实例的状态。如果希望能从类的外部创建类的实例,需要声明构造函数为public.
构造函数的名称和类名相同.
构造函数不能有返回值.
构造函数可以带参数,可以被重载.
举例见代码:
enum gender{男,女} class Program { static void Main(string[] args) { int number = 28899; Console.WriteLine(Convert.ToChar(number)); person p1 = new person();//在创建对象时候就会执行一遍构造方法 p1.Name = "翟群"; p1.Age = 20; p1.Sex = gender.女; p1.SayHello(); person p2=new person("张三",18,(gender)Enum.Parse(typeof(gender),"男"));//在生孩子的时候就将年龄,性别,名字初始化 } } class person { public person() { } private string name; private int age; private gender sex; public person(string n, int a, gender s) { name = n; age = a; sex = s; } public string Name { set { name = value; } get { return name; } } public int Age { set { age = value; } get { return age; } } public gender Sex { set { sex = value; } get { return sex; } } public void SayHello() { Console.WriteLine("你好,我叫{0},我今年{1}岁了,我是{2}生", name, age, sex); Console.ReadKey(); } }
class Program { static void Main(string[] args) { Student s1 = new Student() { Name="ha",Age=18,Gender='男',Math=90,Yuwen=89,English=100};//通过无参数构造函数创建对象 s1.SayHello(); s1.CalulateScores(s1.Name, s1.Yuwen, s1.Math, s1.English); Console.ReadKey(); Student s2 = new Student("hehe", '女');//调用带可选参数构造函数 s2.SayHello(); s2.CalulateScores(s2.Name, s2.Yuwen, s2.Math, s2.English); Console.ReadKey(); Student s3 = new Student("meimei",'女',20);//调用带参数的构造函数 s3.SayHello(); s3.CalulateScores(s3.Name, s3.Yuwen, s3.Math, s3.English); Console.ReadKey(); } } class Student { private string name; private char gender; private int age; private int yuwen; private int math; private int english; public Student() { }//无参数构造函数 public Student(string name, char gender, int age)//带参数的构造函数,重载 { this.name = name; this.gender = gender; this.age = age; } public Student(string n, char g, int a=18, int y = 0, int m=60,int english=60)//包含可选参数的构造函数,重载 { name = n; gender = g; age = a; yuwen = y; math = m; this.english = english ; // English = english;也可以,但是一般情况下,属性用来外界访问字段所使用,一般类的内部,不使用属性 } public void SayHello(){ Console.WriteLine("我叫{0},我几年{1}岁了,我是{2}生",name,age,gender); } public void CalulateScores(string name,int yuwen,int math,int english){ int sum=yuwen+math+english; float averge=sum/3; Console.WriteLine("我叫{0},总分是{1},平均分是{2}", name, sum, averge); } public string Name { set { name = value; } get { return name; } } public char Gender { set { gender = value; } get { return gender; } } public int Age { set { age = value; } get { return age; } } public int Yuwen { set { yuwen = value; } get { return yuwen; } } public int Math { set { math = value; } get { return math; } } public int English { set { english = value; } get { return english; } } }
作业一:
我的code
class Program { static int ReadInt() { int distance; Console.WriteLine("请输入您的车程"); while (true) { try { distance = Convert.ToInt32(Console.ReadLine()); if (distance>0) { break; } Console.WriteLine("距离不能小于等于0 "); } catch (System.Exception ex) { Console.WriteLine("您的输入有误,请重新输入"); } } return distance; } static void Main(string[] args) { int inputDistance = ReadInt();//int inputDistance=int.parse(Console.ReadLine()); Ticket t = new Ticket(inputDistance); int distance = t.Distance; t.ShowCaculateMoney(distance); } } class Ticket { public Ticket(int distance) { this.distance = distance; } private int distance; public int Distance { get { return this.distance; } } public void ShowCaculateMoney(int distance) { double sum = 0; if (distance<100) { sum = distance * 1; Console.WriteLine("不打折,您的车程在100公里以内,应付款{0}",sum); } else if (distance>100 &&distance<200) { sum = distance * 0.95; Console.WriteLine("打九点五折,您的车程在100-200公里以内,付款{0}", sum); } else if (distance>200 && distance<300) { sum = distance * 0.9; Console.WriteLine("打九折您的车程在200-300公里以内,应付款{0}", sum); } else { sum = distance* 0.8; Console.WriteLine("打八折您的车程在100公里以内,应付款{0}", sum); } Console.ReadKey(); } }
老师的讲解
class Program { static void Main(string[] args) { while (true) { Console.WriteLine("请输入您的行程"); int inputDistance = int.Parse(Console.ReadLine()); try { Ticket t = new Ticket(inputDistance); t.ShowPrice(); } catch (System.Exception ex) { Console.WriteLine(ex.Message); } } } } class Ticket{ private int distance; private double price; public int Distance { get { return this.distance; } } public double Price { get { return this.price; } } public Ticket(int dis) { this.distance = dis; if (dis<0) { //抛出一个异常,让main方法知道出错,不再继续执行后面的语句,也可以用一个out bool 参数 throw new Exception("输入了负数"); } else if (dis>0 && distance<101) { price = dis; } else if(dis>101 && distance<201) { price=dis*0.95; } else if (dis>201 && distance<301) { price = dis * 0.9; } else { price = dis * 0.8; } } public void ShowPrice() { Console.WriteLine("您的行程为{0},应付款为{1}", distance, price); } }
作业二:
我的code
enum gender{男,女} class Program { static void Main(string[] args) { Console.WriteLine("给您家即将出生的小狗狗起个名字吧"); string name = Console.ReadLine(); Dog dog = new Dog(name); Console.WriteLine("主人,你好,你叫{0},今年{1}岁,我是{1}生,你有什么吩咐吗?", dog.Name, dog.Age, Convert.ToString(dog.Sex)); while (true) { string Replay = Console.ReadLine(); dog.Speak(Replay); if (dog.Age >= 10) { break; } } } } class Dog { private string name; private int age; private gender sex; private int eatTimes; private int sleepTimes; public string Name { get { return name; } } public int Age { get {return age; }} public gender Sex { get { return sex; } } public Dog(string name) { this.name = name; this.age = 0; Random random = new Random(); int flag=random.Next(0,1); if (flag==0) { sex = gender.男; } else { sex = gender.女; } this.eatTimes = 0; this.sleepTimes = 0; } public void Speak(string replay) { if (replay.Contains("饭")) { Eat(); } else if (replay.Contains("睡觉")) { Sleep(); } else { Console.WriteLine("呜呜听不懂,我只会吃饭睡觉"); } } public void Eat() { eatTimes++; if (eatTimes % 3 == 0 && eatTimes != 0) { Console.WriteLine("这是我今天的第三次饭了,太饱了,我想睡觉"); } else { Console.WriteLine("又有好吃的了,噢耶"); } } private void Sleep() { if (eatTimes==0) { Console.WriteLine("我好饿,我睡不着"); } else if (eatTimes%3==0 ) { sleepTimes++; Console.WriteLine("我马上睡觉"); if (sleepTimes%3==0) { GrowUp(); } } else { Console.WriteLine("我想吃东西了,我没有能量,睡不着"); } } public void GrowUp( ) { Console.WriteLine("哈哈,我又长大一岁了"); age++; if (age>=10) { Console.WriteLine("我老了,我走了....."); } } }
老师的讲解
class Program { static void Main(string[] args) { Console.WriteLine("如果是男机器人,取名为:"); string boy = Console.ReadLine(); Console.WriteLine("如果是女机器人,取名为:"); string girl = Console.ReadLine(); Robot robot = new Robot(boy,girl); Console.WriteLine("我是编号89757机器人,很高兴来到这个世界"); while (robot.GrowUp()) { Console.WriteLine("现在吃饭吗?y/n"); string replay = Console.ReadLine(); if (replay=="y") { robot.Eat(); } Console.WriteLine("你睡觉吗?y/n"); if (Console.ReadLine()=="y") { robot.Sleep(); } Console.WriteLine("我叫{0},{1}岁了,我是{2}生", robot.Name, robot.Age , robot.Gender); } Console.WriteLine("拜拜了,我已经来着{0}年了", robot.Age); Console.ReadKey(true);//按一个键,结束运行,不现实按键的值 } }
class Robot { private string name; public string Name { get { return name; } set { name = value; } } private int age; public int Age { get { return age; } } private char gender; public char Gender { get { return gender; } } private int eatCount; private int sleepCount; public Robot(string boy, string girl) { Random random = new Random(); int res = random.Next(0, 2);//随机生成0或1 if (res==1) { this.gender='男'; this.name=boy; } else{ this.gender='女'; this.name=girl; } // this.gender=random.Next(2)==1? '男' : '女'; 可三元表达式较为方便 // this.name = this.gender == '男' ? boy : girl; this.age = 0; } public void Eat() { eatCount++; Console.WriteLine("我吃饭了哈"); } public void Sleep() { if (eatCount>=2) { eatCount = 0; sleepCount++; } else { Console.WriteLine("我还没吃饭呢,呜呜"); } } public bool GrowUp() { if (sleepCount>=2) { this.age++; } if (age>3) { return false; } return true; } }