面向对象的三个特征:封装,继承,多态
继承
我们在类中,如果需要写一些重复的成员,我们可以将这些重复的成员单独封装到一个类中,作为子类的父类;
父类也可叫做基类
子类也可叫做派生类
子类继承了父类的属性和方法,但是并没有继承父类的私有字段。
子类并没有继承了父类的构造函数。但是子类会默认的调用父类无参数的构造函数,用于创建父类对象,让子类可以使用父类中的成员。如果在父类中重写了一个有参数的构造函数之后,那个无参数的就被干掉了,子类无法调用,会报错。
解决办法:
1、在父类中重新写一个无参的构造函数
2、在子类中显示的调用父类的构造函数,使用关键字:base()
父类构造函数,
public Person(string name ,int age ,char gender)
{
this.Age = age;
this.Name = name;
this.Gender = gender;
}
子类构造函数
public Student(string name,int age,char gender,int id)
:base(name,age,gender)// 使用关键字调用父类的有参构造函数
{
this.Id = id;//只需要赋值id即可,其余的在父类的构造函数中已经实现了
}
继承的特性:
1、继承的单根性:一个子类只能有一个父类
2、继承的传递性
父类
class Person
{
private string _name;
private int _age;
private char _gender;
public string Name { get => _name; set => _name = value; }
public int Age { get => _age; set => _age = value; }
public char Gender { get => _gender; set => _gender = value; }
public void CHLSS()
{
Console.WriteLine("吃喝拉撒睡");
}
}
子类
class Student:Person
{
private int _id;
public int Id { get => _id; set => _id = value; }
public void Study()
{
Console.WriteLine("学生会学习");
}
}
继承于student,拥有student的方法属性。因为student继承与person,所以teacher也拥有person 的方法属性
class Teacher:Student
{
private double _salary;
public double Salary { get => _salary; set => _salary = value; }
public void Tech()
{
Console.WriteLine("老师会教书");
}
}
object是所有类的基类
new关键字
1、创建对象
2、隐藏从父类哪里集成过来的同名成员。
隐藏的后果就是调用不到父类的同名成员。
父类中有 sayhello方法
class Programer:Person
{
public Programer(string name,int age,char gender,int workyear)
:base(age,name,gender)
{
this.Workyear = workyear;
}
private int _workyear;
public int Workyear { get => _workyear; set => _workyear = value; }
public void ProgramerSayHello()
{
Console.WriteLine($"我叫{this.Name},我是一名程序员,,我是{this.Gender}生,我今年{this.Age}岁,我的工作年限是{this.Workyear}年");
}
public new void SayHello()
{
Console.WriteLine("大家好!我是记者。");
}
}
子类中有同名成员,此时代码编译能通过但是会有下划线提示错误,加上new关键字可以隐藏父类中的同名方法,不再报错
class Programer:Person
{
public Programer(string name,int age,char gender,int workyear)
:base(age,name,gender)
{
this.Workyear = workyear;
}
private int _workyear;
public int Workyear { get => _workyear; set => _workyear = value; }
public void ProgramerSayHello()
{
Console.WriteLine($"我叫{this.Name},我是一名程序员,,我是{this.Gender}生,我今年{this.Age}岁,我的工作年限是{this.Workyear}年");
}
public new void SayHello()//使用new关键字隐藏父类的同名成员
{
Console.WriteLine("大家好!我是记者。");
}
}
里氏转换
定义:
1、子类可以复制给父类
// 子类可以赋值给父类
Student s = new Student();
Person p = s;
2、如果父类中装的是子类对象,那么可以将父类强转为子类对象
// 子类可以赋值给父类
//person是student的父类
Student s = new Student();
Person p = new Student();
//如果父类中装的是子类对象,那么可以将父类强转为子类对象
Student ss = (Student)p;
ss.StudentSayHello();
子类对象可以调用父类对象的成员,父类对象不能调用子类对象的成员。
3、
is:表示类型转换,如果能够转换成功,则返回一个true,否则返回false
//is的用法
if (p is Student)
{
Student ss = (Student)p;
ss.StudentSayHello();
}
else
{
Console.WriteLine("转换失败");
}
as:表示类型转换,如果能够转换则返回对应的对象,否则返回一个null
//as的用法
Student t = p as Student;
Protected修饰符
受保护的:可以在当前类的内部以及该类的子类中访问。
ArrayList集合的长度问题
每次集合中实际包含的元素个数(count),超过了可以包含的元素个数(capcity)的时候,集合就会向内存中申请多一倍的空间,来保证集合的长度一直够用。
hashrable集合(键值对集合)
在键值对集合当中,我们是根据键去找值的。
键值对象[键]=值;
键值对集合中,键只能是唯一的但是值可以是重复的。
1、ContainsKey(键名);判断是否有指定键名,返回值为bool
2、ContainsValue(键值);判断是否有指定键值,返回值为bool
3、Remove(键名);移除指定键名所对应的元素
4、Clear();清空集合中的所有元素
Hashtable ht = new Hashtable();
ht.Add(1, "张三");
ht.Add(2,true);
ht.Add(false, "错误的");
ht[1]=250;//这也是一种添加数据的方式
if (ht.ContainsKey(true))
{
Console.WriteLine("已经包含true这个键了");
}
if (ht.ContainsValue("张三"))
{
Console.WriteLine("已经包含张三这个键值了");
}
ht.Clear();//清空集合内所有的元素
ht.Remove(false);//移除键名为false元素
//在键值对集合中是根据键去找值
//ht.Keys 键的集合
//ht.Values值的集合
//循环打印对应键的值
foreach (var item in ht.Keys)
{
Console.WriteLine($"键是==={item};值是==={ht[item]}");
}
c#:强类型语言。在代码中必须多每一个变量类型有一个明确的定义
foreach循环
static void Main(string[] args)
{
int[] nums = { 1, 2, 3, 5, 6, 3, 2, 3, 2, 1, 5, 2 };
for (int i = 0; i < nums.Length; i++)
{
Console.WriteLine(nums[i]);
}
Console.WriteLine("=============");
foreach (var item in nums)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
简体字转繁体字
//将用户输入的简体字转为繁体字
class Program
{
private const string jian = "啊飞好就看了我饿人他才";//简体字集合
private const string fan = "123就看了我饿人他才";//繁体字集合
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
for (int i = 0; i < jian.Length; i++)
{
ht.Add(jian[i], fan[i]);
}
Console.WriteLine("请随便输入");
string input = Console.ReadLine();
for (int i = 0; i < input.Length; i++)
{
if (ht.ContainsKey(input[i]))
{
Console.WriteLine(ht[input[i]]);
}
else
{
Console.WriteLine(input[i]);
}
}
Console.ReadKey();
}
}
patch类,
patch是一个静态类,不需要创建对象, 直接类名.方法名即可
1、Patch.GetFileNmae();//获取文件名以及扩展名
2、Path.GetFileNameWithoutExtension(str);//获取文件名
3、Path.GetFullPath(str);//获取文件绝对路径
4、Path.GetExtension(str);//获取文件的扩展名
5、Path.GetDirectoryName(str);//获取文件的目录信息
6、Console.WriteLine(Path.Combine(@”c:\a\c”,”b.txt”));连接两个字符串作为路径
string str = @"e:\Users\Lenovo\Desktop\start.wav";
//获取文件名
Console.WriteLine(Path.GetFileNameWithoutExtension(str));
//获取文件全路径
Console.WriteLine(Path.GetFullPath(str));
//获取文件扩展名
Console.WriteLine(Path.GetExtension(str));
//获取文件路径
Console.WriteLine(Path.GetDirectoryName(str));
//获取文件名称以及扩展名
Console.WriteLine(Path.GetFileName(str));
//连接两个字符串作为路径
Console.WriteLine(Path.Combine(@"c:\a\c","b.txt"));
Console.ReadKey();
File类
File是一个静态类,不需要创建对象, 直接类名.方法名即可
1、File.Create(path);//创建文件
2、File.Copy(path);//复制文件
3、File.Delete(path);//删除文件
4、File.Move(path);//移动文件
5、File.Exists(path);//检查文件是否存在 返回bool
//创建文件
File.Create( @"e:\Users\Lenovo\Desktop\start.txt");
//复制文件
File.Copy(@"e:\Users\Lenovo\Desktop\start.wav", @"e:\Users\Lenovo\Desktop\start.zip");
//删除文件
File.Delete(@"e:\Users\Lenovo\Desktop\start - 副本.wav");
//移动文件
File.Move(@"e:\Users\Lenovo\Desktop\start.wav", @"d:\start.wav");
//检查指定文件是否存在,返回bool
File.Exists(@"e:\Users\Lenovo\Desktop\start.txt");
6、File.ReadAllBytes(path);//打开一个二进制文件,读入到字节数组中,然后关闭文件
byte[] buffer = File.ReadAllBytes(@"e:\Users\Lenovo\Desktop\start.txt");
//将字节数组中的每一个元素都按照编码格式解码成字符串
string s = Encoding.GetEncoding("UTF-8").GetString(buffer);
Console.WriteLine(s);
Console.ReadKey();
7、File.WriteAllBytes(path,buffer);//以字节数组的方式写入文件,文件如果不存在则创建,若存在则覆盖
//写入文件,如果文件存在则覆盖没有则创建
string str = "今天天气不错";
byte[] buffer = Encoding.Default.GetBytes(str);
File.WriteAllBytes(@"e:\Users\Lenovo\Desktop\test.txt",buffer);
8、 File.ReadAllText读取所有文本 File.ReadAllLines读取所有行
string str = "今天天气不错";
byte[] buffer = Encoding.Default.GetBytes(str);
File.WriteAllBytes(@"e:\Users\Lenovo\Desktop\test.txt", buffer);
string str1 = File.ReadAllText(@"e:\Users\Lenovo\Desktop\test.txt",Encoding.Default);
Console.WriteLine(str1);
string[] contens = File.ReadAllLines(@"e:\Users\Lenovo\Desktop\test.txt",Encoding.Default);
foreach (var item in contens)
{
Console.WriteLine(item);
}
Console.ReadKey();
9、 File.WriteAllLines:以行的形式写入文件,写入一个字符串就换一行
File.WriteAllText:以文本的形式写入文件
两个方法都会覆盖原本的类型
File.WriteAllLines(@"e:\Users\Lenovo\Desktop\start.txt",new string[] { "aoe","ewu"});
File.WriteAllText(@"e:\Users\Lenovo\Desktop\start.txt","你好,世界!");
10、File.AppendAllText 追加写入文件,不会覆盖原本的类容
File.AppendAllText(@"e:\Users\Lenovo\Desktop\start.txt", "你好,世界!");
相对路径与绝对路径
绝对路径:通过给定的这个路径直接能在我的电脑中找到这个文件。
相对路径:文件相对于应用程序的路径。
结论:
在开发过程中尽量使用相对路径。
装箱、拆箱
装箱:就是将值类型转换为引用类型。
拆箱:将引用类型转换为值类型。
FileStream(文件流)
读取数据:
//FileStream
//1、创建FileStream对象
//==========================读取数据
FileStream fs = new FileStream(@"e:\Users\Lenovo\Desktop\start.txt",FileMode.OpenOrCreate,FileAccess.Read);
byte[] buffer = new byte[1024 * 1024*5];//声明字节数组,并设置大小为5
// 读取的返回数据字节数组,存放数据的首地址,最多读取的数量
//r为读取的实际字节数
int r= fs.Read(buffer,0,buffer.Length);
//将字节数组中每一个元素按照指定的编码格式解码成字符串(需要按转换的字节数组,开始转换的序号,转换个数)
string s = Encoding.UTF8.GetString(buffer,0,r);
//关闭流,
fs.Close();
//释放流所占用的资源
fs.Dispose();
Console.WriteLine(s);
Console.ReadKey();
}
上面可以看到,我们在使用完成后需要关闭文件流和手动释放文件资源。这对我们来说很不习惯,还有另一种方法就是将创建文件流对象的过程写在using当中,会自动的帮助我们释放流所占用的资源。
//使用filestream写入数据
using (FileStream fsWrite=new FileStream(@"e:\Users\Lenovo\Desktop\start.txt", FileMode.OpenOrCreate, FileAccess.Write))
{
string str = "你好,义昆!";
byte[] buffer = Encoding.UTF8.GetBytes(str);
fsWrite.Write(buffer, 0, buffer.Length);
}
StreamReader读取文本文件
static void Main(string[] args)
{
//使用StreamReader来读取文件
using (StreamReader sr = new StreamReader(@"e:\Users\Lenovo\Desktop\start.txt"))
{
while(!sr.EndOfStream)//没有读取到最后一行,就一直循环读取
{
Console.WriteLine(sr.ReadLine());
}
Console.ReadKey();
}
}
StreamWriter写入文本文件
//使用StreamWrter写入文本文件
////(路径 ,是否追加)
using (StreamWriter sw = new StreamWriter(@"e:\Users\Lenovo\Desktop\start1.txt",true))
{
sw.Write("今天天气不错");
}