2020/10/27C#开启新征程
前言
类,this关键字,构造函数,访问修饰符,继承的了解
提示:以下是本篇文章正文内容,下面案例可供参考
一、类
1.类的定义
代码如下(示例):
定的定义语法:
[访问修饰符] class 类名
{
成员;
......
}
类中可以包含变量的定义、方法。
2.访问修饰符以及属性
【@】类中成员都需要定义访问级别。访问级别用于控制成员在哪些地方可以被访问,这样达到面向对象中“封装”的目的.
访问修饰符:
1.private:私有的,只能在当前类的内部访问,出了这个类就访问不到了
2.public:公开的,公共的,在哪都可以访问
3,.internal:只能在当前程序的内部访问,出了这个程序就访问不到了。类默认就是internal
4.protected:只能在当前类的内部,以及该类的子类中访问
5.类只能被public和internal修饰,默认就是internal
6.protected internal:定义的字段或者类 拥有protected 和interal 的访问权限,不禁在本项目可以访问,出了本项目的其他派生类也可以访问。
注意:子类的访问权限不能高与父类的访问权限
【@】属性的分类:
属性可分为:
读写: 既有get 、也有set
只读: 只有get 没有set
只写: 只有set 没有get (意义不大)
//属性如何保护字段:
1、将字段私有化,保护数据
2、用属性的get 和set访问器 对字段赋值和取值 进行控制,从而达到保护字段的目的。
3.拿来存数据
代码如下(示例):
class Program
{
static void Main(string[] args)
{
//创建对象
//语法: 类 对象名 = new 类();
Student stu1 = new Student();
stu1.Name = "刚哥";
stu1.Age = 18;
stu1.Gender = '女';
stu1.Height = 170;
对象名.方法名
stu1.CHLSS();
stu1.Learn();
stu1.SayHello();
Console.ReadKey();
}
}
// 定义了一个学生类
public class Student
{
/// <summary>
/// 构造方法
/// </summary>
public Student()
{
}
//成员:属性(特征) 方法(行为)
//姓名 性别 年龄 身高
//字段(这里需要把字段改为私有从而达到用属性保护字段的作用)
private string name;
//属性
public string Name
{
get { return name; }
set
{
if (value == "李思思")
{
name = "张三";
}
else
{
name = value;
};
}
}
//年龄
private int age;
public int Age
{
get { return age; }
set
{
if (value > 0 && value < 110)
{
age = value;
}
else
{
age = 0;
};
}
}
//性别
private char gender;
public char Gender
{
get { return gender; }
set
{
if (value == '男' || value == '女')
{
gender = value;
}
else
{
gender = '男';
};
}
}
//身高
private int height;
public int Height
{
get { return height; }
set
{
if (value > 100 && value < 300)
{
height = value;
}
else
{
height = 170;
};
}
}
//吃饭 睡觉 学习
public void CHLSS()
{
Console.WriteLine("我会吃喝啦撒睡!");
}
public void Learn()
{
Console.WriteLine("我会HelloWrold!");
}
public void SayHello()
{
Console.WriteLine("我叫{0},是{1}生,{2}岁,身高是{3}", name, gender, age, height);
}
}
3.构造函数
1.构造方法用来创建对象,并且可以在构造函数中对对象进行初始化。
2.构造函数是用来创建对象的特殊方法,方法名和类名一样,没有返回值,连void都不用。
3.构造函数可以有参数,new对象的时候传递函数参数即可
4.如果不指定构造函数,则类有一个默认的无参构造函数。如果指定了构造函数,则不再有默认的无参构造函数,如果需要无参构造函数,则需要自己来写。
5.构造函数可以重载,也就是有多个参数不同的构造函数。
代码如下(示例):
namespace 构造函数
{
class Program
{
static void Main(string[] args)
{
Student stu2 = new Student("abc", 18,'男',90,100,100);
}
}
}
public class Student
{
//构造函数 特殊的方法
//构造函数可以重载
//public Student()
//{
// //Console.WriteLine("我是构造函数,我什么都没有做!");
//}
//初始化对象,在对象开new的时候就已经给值了。
public Student(string name, int age, char gender, int chinese, int english, int math)
{
Name = name;
Age = age;
Gender = gender;
Chinese = chinese;
Math = math;
English = english;
}
//name
private string name;
//属性
public string Name
{
get { return name; }
set
{
if (value != "")
{
name = value;
}
else
{
name = "匿名";
}
}
}
//年龄
private int age;
public int Age
{
get { return age; }
set
{
if (value > 0 && value <= 100)
{
age = value;
}
else
{
age = 0;
}
}
}
//性别
private char gender;
public char Gender
{
get { return gender; }
set
{
if (value == '男' || value == '女')
{
gender = value;
}
else
{
gender = '男';
}
}
}
//语文
private int chinese;
public int Chinese
{
get { return chinese; }
set
{
if (value >= 0 && value <= 100)
{
chinese = value;
}
else
{
chinese = 0;
}
}
}
//数学
private int math;
public int Math
{
get { return math; }
set
{
if (value >= 0 && value <= 100)
{
math = value;
}
else
{
math = 0;
}
}
}
//英语
private int english;
public int English
{
get { return english; }
set
{
if (value >= 0 && value <= 100)
{
english = value;
}
else
{
english = 0;
}
}
}
//打招呼
public void SayHello()
{
Console.WriteLine("你好!,我叫{0},今年{1}岁,是{2}生", Name, Age, Gender);
}
//获取成绩的方法
public void GetScore()
{
Console.WriteLine("我叫{0},这次考试总成绩为{1}分,平均成绩为{2}分", this.Name, this.Chinese + this.Math + this.English, (this.Chinese + this.Math + this.English) / 3);
}
}
3.this关键字的使用
this关键字的两个作用:
1.this关键字表示当前类的对象
2.在一个类中有多个构造函数,造成代码冗余调用当前类中的构造函数,以便解决代码冗余
代码如下(示例):
class Program
{
static void Main(string[] args)
{
//this : 表示当前类的对象
Student stu1 = new Student("张三", 12, '女', 100, 100, 100);
}
}
public class Student
{
//构造函数 特殊的方法
//构造函数可以重载
public Student()
{
//Console.WriteLine("我是构造函数,我什么都没有做!");
}
public Student(string name, int age, char gender)
{
this.Name = name;
this.Age = age;
this.Gender = gender;
}
//如果希望在调用当前类中的另一个构造函数 ,在这个构造函数的方法头部后面加:this(参数列表)
//初始化对象
public Student(string name, int age, char gender, int chinese, int english, int math)
: this(name, age, gender)
{
//Name = name;
//Age = age;
//Gender = gender;
// Student(name, age, gender);
Chinese = chinese;
Math = math;
English = english;
}
//name
private string name;
//属性
public string Name
{
get { return name; }
set
{
if (value != "")
{
name = value;
}
else
{
name = "匿名";
}
}
}
//年龄
private int age;
public int Age
{
get { return age; }
set
{
if (value > 0 && value <= 100)
{
age = value;
}
else
{
age = 0;
}
}
}
//性别
private char gender;
public char Gender
{
get { return gender; }
set
{
if (value == '男' || value == '女')
{
gender = value;
}
else
{
gender = '男';
}
}
}
//语文
private int chinese;
public int Chinese
{
get { return chinese; }
set
{
if (value >= 0 && value <= 100)
{
chinese = value;
}
else
{
chinese = 0;
}
}
}
//数学
private int math;
public int Math
{
get { return math; }
set
{
if (value >= 0 && value <= 100)
{
math = value;
}
else
{
math = 0;
}
}
}
//英语
private int english;
public int English
{
get { return english; }
set
{
if (value >= 0 && value <= 100)
{
english = value;
}
else
{
english = 0;
}
}
}
//打招呼
public void SayHello()
{
Console.WriteLine("你好!,我叫{0},今年{1}岁,是{2}生", Name, Age, Gender);
}
//获取成绩的方法
public void GetScore()
{
Console.WriteLine("我叫{0},这次考试总成绩为{1}分,平均成绩为{2}分", this.Name, this.Chinese + this.Math + this.English, (this.Chinese + this.Math + this.English) / 3);
}
}
二、字符串
1.可以看出只读的字符数组
a.C#中字符串有一个重要的特性:不可变性,字符串一旦声明就不再可以改变。只能把他转为char数组才能修改,但是他现在并不是字符串了。
b.c#中有个字符串拘留池。就是放置你使用过的字符串
2.字符串的常用方法:
ToCharArray(); 字符串转字符数组
ToUpper(): 转大写
ToLowwer(): 转小写
Trim(): 去掉两端的空格
Equals();比较字符串是否相等,区分大小写
string[] Split(params char[] separator)
将字符串按照指定的分割符分割为字符串数组;
Replace(string oldValue, string newValue): 字符串替换
Contains(string value)判断字符串中是否含有子串value
Substring(int startIndex) , 取子字符串 取从位置startIndex开始到最后的子字符串;
代码如下(示例):
class Program
{
static void Main(string[] args)
{
//字符串可以看出是只读字符char数组
string str = "absdasdasd";
//读
char c = str[3];
//Console.WriteLine(c);
//赋值
//str[3] = 'm';
//把字符串转换为字符数组,这样就可以对字符串进行改变了。
char[] cc = str.ToCharArray();
cc[3] = 'm';
//Console.WriteLine(cc[3]);
//把字符数组转换为字符串
str = new string(cc);
//for (int i = 0; i < str.Length; i++)
//{
// Console.WriteLine(str[i]);
//}
//字符串具有不可变性
string str1 = "abc";
str1 = "ccc";//他这里不是修改了,而是指向了另一块儿内存地址
Console.ReadLine();
}
}
三、继承
1、继承
所解决的问题:代码冗余
好处 :让类与类之间产生了关系,为多态打下了基础。
缺点:打破了类的封装性。带来了安全隐患。
子类继承了父类的哪些成员?
—>属性、方法,并没有继承私有字段,和构造函数
—>子类调用的是父类中默认的无参数的构造函数,父类有可能在默认的无参数的构造函数中对数据进行初始化。
关键字:
this:
—>代表当前类的对象
—>在子类中显示的调用自己的构造函数
base:
—>指向父类的一个引用,通过base,可以调用父类的成员,不代表父类对象
new:
—>创建对象
—>隐藏父类的成员
—>Object是一切类的父类(基类)
2、继承的两大特性
---->单根性
----一个儿子只能有一个爹,干爹不算。(object、接口都是干爹)
---->传递性
----继承的成员可以一层一层的向下传递。
注:内存中除了栈和堆之外,还有一个方法表,方法表中有一个静态存储区,专门用来存放静态成员(静态成员一经声明就一直占用内存,直道程序结束才会释放资源,但是他有一个好处就是资源共享,比如全局变量)
注:类不写public默认是internal,类里面的成员不写,那么默认就是private
代码如下(示例):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 继承
{
class Program
{
static void Main(string[] args)
{
//封装、继承、多态
//封装:1、方便多次调用
//为什么要使用继承?
//我们在设计类的时候,会发现,有很多类中会具有相同的成员,为了减少代码的冗余,我们将这些相同的成员,提取出来,单独的封装成了一个类
//作为其他的类"父类或者基类",其他类是这个类的"子类或者派生类"
// Student student = new Student();//创建对象、在堆中开辟空间,调用对象的构造函数
//在c#中,所有的类都直接或者间接的继承于Object类
//我们看一个类是否继承与另一类,首先要检查是否有:冒号,如果没有冒号,则这个类继承于object,如果有冒号,则直接继承与冒号后面的类,间接继承与object
//一个子类继承了一个父类,那么这个子类继承了这个父类中的那些成员?
//子类对象能够点出来哪些成员,凡是点出来的成员们,都是继承过来的成员,点不出来的,我们就说你没有继承。
//子类并没有继承的私有字段,而继承了父类的属性、
//子类有没有继承父类的函数(PersonSayHello())',子类同样继承了父类的函数
//子类是否继承了父类的构造函数?
//构造函数问题:
//子类并没有继承父类的构造函数,因为在创建子类对象的时候,并调用不到父类的构造函数
//我们在创建子类对象的时候发现,会先执行父类的构造函数,也就是说,子类并没有继承父类的构造函数,而是会调用父类那个默认的无参数的构造函数。
//子类为什么要调用父类那个默认的无参数的构造函数?
//因为父类有可能在自己默认的无参数的构造函数中,对成员进行初始化,如果子类想要得到父类初始化后的成员,那么子类需要去调用父类默认的无参数的构造函数
// F10是在当前的函数执行过程中进行单步调试。不会进入到执行函数的内部进行更加详细的调试过程。
//F11是需要进入到当前执行函数的内部,进行更加详细的调试的过程。
Student student = new Student();
student.Study();
PerSion p = new PerSion();
// p.Study();
Console.ReadKey();
}
}
//静态类这个能不写尽量不要写,太占用内存
static class staticPersion
{
//所有成员都是静态的。
}
class PerSion
{
public PerSion(string name,int age,char gender)
{
this.Age = age;
this.Gender = gender;
this.Name = name;
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
private char gender;
public char Gender
{
get { return gender; }
set { gender = value; }
}
private string contry;
public string Contry
{
get { return contry; }
set { contry = value; }
}
//当我们在父类中重写了一个有参数的构造函数之后,那么默认无参数的就被干掉了,子类就调用不到了
//解决方法有两个:
//1.在父类中重写一个无参数的构造函数,基本不用,因为没有太大的意义
//2.选择在子类中显示的调用父类有参数的构造函数使用关键字base.
public PerSion()
{
}
public void PerSionSay()
{
Console.WriteLine("Persion Hello");
}
public void Study()
{
Console.WriteLine("我是老师我爱学习");
}
}
//this:代表当前类对象 调用本类的构造函数
//base:调用父类的成员,一个指向父类的引用,通过base可以调用父类的成员,但是并不能代表父类对象
//在创建子类对象的时候,会先执行并调用父类的构造函数
class Student :PerSion
{
public Student()
{
}
public Student(string name,int age,char gender,int id):base(name,age,gender)//显示的调用父类指定的构造函数
{
this.Id = id;
}
//学号
private int id;
public int Id
{
get { return id; }
set { id = value; }
}
public void StudentSayHello()
{
Console.WriteLine("我是一个学生");
}
//如果子类和父类定义了相同的方法,那么可以用new关键字显式隐藏子类中的方法
public new void Study()
{
base.Study();//通过base显式调用父类的成员
Console.WriteLine("我是学生爱学习");
}
}
class Teacher:Student
{
public void TeacherSayHello()
{
Console.WriteLine("我是一个老师");
}
}
class Driver:Teacher
{
private int driverTime;
public int DriverTime
{
get { return driverTime; }
set { driverTime = value; }
}
public void DriverSayHello()
{
Console.WriteLine("我是司机");
}
}
}
总结
提示:多看看,多写写,多总结,得到的总是会多一点。