我们知道面向对象的三个特征,封装,继承和多态。我们前面已经学习了如何封装在类中封装方法。现在我们系统学习什么是继承。
我们下面写几个类:student teacher driver几个类
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 草稿1 8 { 9 public class Student 10 { 11 private string _name; 12 public string Name 13 { 14 get { return _name; } 15 set { _name = value; } 16 } 17 18 private int _age; 19 public int Age 20 { 21 get { return _age; } 22 set { _age = value; } 23 } 24 25 private char _gender; 26 public char Gender 27 { 28 get { return _gender; } 29 set { _gender = value; } 30 } 31 32 private int _id; 33 public int Id 34 { 35 get { return _id; } 36 set { _id = value; } 37 } 38 39 public void CHLSS() 40 { 41 Console.WriteLine("吃喝拉撒睡"); 42 } 43 public void Study() 44 { 45 Console.WriteLine("学生会学习"); 46 } 47 } 48 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 草稿1 8 { 9 public class Teacher 10 { 11 private string _name; 12 public string Name 13 { 14 get { return _name; } 15 set { _name = value; } 16 } 17 18 private int _age; 19 public int Age 20 { 21 get { return _age; } 22 set { _age = value; } 23 } 24 25 private char _gender; 26 public char Gender 27 { 28 get { return _gender; } 29 set { _gender = value; } 30 } 31 32 private double _salary; 33 public double Salary 34 { 35 get { return _salary; } 36 set { _salary = value; } 37 } 38 39 public void CHLSS() 40 { 41 Console.WriteLine("吃喝拉撒睡"); 42 } 43 public void Teach() 44 { 45 46 Console.WriteLine("老师会讲课"); 47 } 48 } 49 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 草稿1 8 { 9 public class Driver 10 { 11 private string _name; 12 public string Name 13 { 14 get { return _name; } 15 set { _name = value; } 16 } 17 18 private int _age; 19 public int Age 20 { 21 get { return _age; } 22 set { _age = value; } 23 } 24 25 private char _gender; 26 public char Gender 27 { 28 get { return _gender; } 29 set { _gender = value; } 30 } 31 32 private int _driveTime; 33 public int DriveTime 34 { 35 get { return _driveTime; } 36 set { _driveTime = value; } 37 } 38 39 public void CHLSS() 40 { 41 Console.WriteLine("吃喝拉撒睡"); 42 } 43 44 public void Drive() 45 { 46 Console.WriteLine("司机会开车"); 47 } 48 49 } 50 }
我们会发现这几个类中成员有重复的,方法有重复的,这时我们把这几个类中重复成员单独拿出来,封装一个类,作为这几个类的
父类。所以我们改造如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 草稿1 8 { 9 public class Person 10 { 11 private string _name; 12 public string Name 13 { 14 get { return _name; } 15 set { _name = value; } 16 } 17 18 private int _age; 19 public int Age 20 { 21 get { return _age; } 22 set { _age = value; } 23 } 24 25 private char _gender; 26 public char Gender 27 { 28 get { return _gender; } 29 set { _gender = value; } 30 } 31 32 public void CHLSS() 33 { 34 Console.WriteLine("吃喝拉撒睡"); 35 } 36 } 37 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 草稿1 8 { 9 public class Driver:Person 10 { 11 private int _driveTime; 12 public int DriveTime 13 { 14 get { return _driveTime; } 15 set { _driveTime = value; } 16 } 17 public void Drive() 18 { 19 Console.WriteLine("司机会开车"); 20 } 21 22 } 23 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 草稿1 8 { 9 public class Teacher:Person 10 { 11 private double _salary; 12 public double Salary 13 { 14 get { return _salary; } 15 set { _salary = value; } 16 } 17 18 public void Teach() 19 { 20 21 Console.WriteLine("老师会讲课"); 22 } 23 } 24 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 草稿1 8 { 9 public class Student:Person 10 { 11 private int _id; 12 public int Id 13 { 14 get { return _id; } 15 set { _id = value; } 16 } 17 public void Study() 18 { 19 Console.WriteLine("学生会学习"); 20 } 21 } 22 }
我们可能会在一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类。
首先,子类继承了父类的属性和方法,但是子类并没有继承父类的私有字段。
引出:子类有没有继承父类的构造函数?
子类并没有继承父类的构造函数。但是,子类会默认调用父类无参数的构造函数。创建父类对象,让子类可以使用父类中的成员。
所以,如果父类中重新写了一个有参数的构造函数之后,那个无参数的就被干掉了,子类就调用不到了,所以子类会报错。
解决办法:1.再父类中重新写一个无参数的构造函数。
2.在子类中显示的调用父类的构造函数,使用关键字:base()
继承的特性
1.继承的单根性:一个子类只能有一个父类。
2.继承的传递性:
New关键字
1)创建对象
2)隐藏从父类那里继承过来的同名成员。隐藏后果就是子类调用不到父类成员。
里氏转换
1)子类可以赋值给父类。如果有一个地方需要一个父类作为参数,我们可以给一个子类代替。
2)如果父类中装的是子类对象,那么可以将这个父类强转为子类对象。
子类对象可以调用父类中的成员,但是父类对象永远都只能调用自己的成员。
类型转换判断的两个关键字
(1)is:表示类型转换,如果能够转换成功,则返回一个true,否则返回一个false。
(2)as:表示类型转换,如果能够转换则返回对应的对象,否则返回一个null。
下面我们做一个综合练习:为了方便观察代码,我们将各种类写到了program类中
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 草稿1 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //创建10个对象,通过一个循环,去调用他们各自打招呼的方法 14 Person[] pers = new Person[10]; 15 Random r = new Random(); 16 for (int i = 0; i < pers.Length; i++) 17 { 18 int rNumber = r.Next(1,7); 19 switch (rNumber) 20 { 21 case 1:pers[i] = new Student(); 22 break; 23 case 2: 24 pers[i] = new Teacher(); 25 break; 26 case 3: 27 pers[i] = new ShuaiGuo(); 28 break; 29 case 4: 30 pers[i] = new MeiLv(); 31 break; 32 case 5: 33 pers[i] = new YeShou(); 34 break; 35 case 6: 36 pers[i] = new Person(); 37 break; 38 39 } 40 } 41 42 for (int i = 0; i < pers.Length; i++) 43 { 44 if (pers[i] is Student) 45 { 46 ((Student)pers[i]).StudentSayHi(); 47 } 48 else if (pers[i] is Teacher) 49 { 50 ((Teacher)pers[i]).TeacherSayHi(); 51 } 52 else if (pers[i] is MeiLv) 53 { 54 ((MeiLv)pers[i]).MeiLvSayHi(); 55 } 56 else if (pers[i] is ShuaiGuo) 57 { 58 ((ShuaiGuo)pers[i]).ShuaiGuoSayHi(); 59 } 60 else if (pers[i] is YeShou) 61 { 62 ((YeShou)pers[i]).YeShouSayHi(); 63 } 64 else 65 { 66 pers[i].PersonSayHi(); 67 } 68 } 69 Console.ReadKey(); 70 } 71 } 72 73 public class Person 74 { 75 public void PersonSayHi() 76 { 77 Console.WriteLine("我是人类"); 78 } 79 } 80 81 public class Student:Person 82 { 83 public void StudentSayHi() 84 { 85 Console.WriteLine("我是学生"); 86 } 87 } 88 89 public class Teacher : Person 90 { 91 public void TeacherSayHi() 92 { 93 Console.WriteLine("我是老师"); 94 } 95 } 96 97 public class MeiLv : Person 98 { 99 public void MeiLvSayHi() 100 { 101 Console.WriteLine("我是美铝"); 102 } 103 } 104 105 public class ShuaiGuo : Person 106 { 107 public void ShuaiGuoSayHi() 108 { 109 Console.WriteLine("我是帅锅"); 110 } 111 } 112 113 public class YeShou : Person 114 { 115 public void YeShouSayHi() 116 { 117 Console.WriteLine("我是野兽"); 118 } 119 } 120 }
关键字protected:
受保护的:可以在当前类的内部以及该类的子类中访问。
两个集合ArrayList和HashTable
ArrayList集合我数组对比:
数组:长度不可变,类型单一
集合:长度任意改变,类型多元化。
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace 草稿1 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 ArrayList list = new ArrayList(); 15 16 list.Add(1); 17 list.Add(3.14); 18 list.Add(true); 19 list.Add("张三"); 20 list.Add('男'); 21 list.Add(5000m); 22 23 for (int i = 0; i < list.Count; i++) 24 { 25 Console.WriteLine(list[i]); 26 } 27 Console.ReadKey(); 28 } 29 } 30 }
ArrayList集合的几个方法:
list.addRange():添加集合元素。
list.Clear():清空所有元素。
list.Remove():删除单个元素,写谁就删谁。
list.RemoveAt():根据下标删除元素。
list.RemoveRange():根据下标删除一定范围的元素
list.Sort():升序排列
list.Reverse():反转
list.Insert():在指定的位置插入一个元素。
list.InsertRange():在指定位置插入一定范围的元素。
list.Contains():判断是否包含某个指定的元素。
ArrayList集合长度问题
每次集合中实际包含的元素个数(count)超过了可以包含的元素的个数(capcity)的时候,集合就会像内存中申请多开辟一倍的
空间,来保证集合的长度一直够用。
HashTable键值对集合
在键值对集合当中,我们是根据键去找值的。
键值对对象[键]=值;
注意:键值对集合当中,键必须是唯一的,而值是可以重复的。
下面我们讨论一下我们如何能够遍历HashTable集合的所有元素,我们一提到便利元素,肯定会想到使用for循环,但是HashTable集合中
键的类型是object,所以可能不是值类型,而且foreach循环的运行效率要比for循环的高,所以我们不能使用for循环,这时我们可以使用foreach。
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace 草稿1 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 Hashtable ht = new Hashtable(); 15 ht.Add(1,"张三"); 16 ht.Add(2,true); 17 ht.Add(3,'男'); 18 ht.Add(false,"错误的"); 19 20 foreach (var item in ht.Keys) 21 { 22 Console.WriteLine(ht[item]); 23 } 24 Console.ReadKey(); 25 } 26 } 27 }
我们除了使用foreach循环添加数据,也可以使用赋值的方法添加数据。这种方式也可以把相同键值的值覆盖掉。
键值对对象[键]=value;
键值对集合常用方法:
ht.ContainsKey();判断是否包含键。
ht.Add():添加键值对元素。
ht.Clear();清空所有元素。
ht.Remove():移除键所对应的元素。
学习几个重要的类
Path类:
Path.Get FileName():获得文件名。
Path.GetFileNameWithoutExtension():获得文件名但是不包括扩展名。
Path.GetExtension():获得文件的扩展名。
Path.GetDirectoryName():获得文件所在的文件夹的名称。
Path.GetFullPath():获得文件所在的全路径。
Path.Combine():链接两个字符串作为路径。
File类:
File.Create():创建一个文件。
File.Delete():删除一个文件。
File.Copy():复制一个文件。