定义一个类
class Child
{
string _name;
string _sex;
int _age;
void Playball()
{
Console.WriteLine("我是C罗,啊哈哈哈哈哈哈!!!");
}
}
主程序为
static void Main(string[] args)
{
Child xiaoming = new Child();
xiaoming._name = "小明";
xiaoming._age = 12;
xiaoming._sex = "男孩";
Console.WriteLine("我是个小{0},我叫{1},我今年{2}岁。",xiaoming._sex,xiaoming._name,xiaoming._age);
xiaoming.Playball();
Console.ReadKey();
}
但是主程序此时会报错,Name,age,sex,Playball()都会产生错误,因为这些是Child类的属性和方法。我们要在主程序里调用的话需要调用的是公共变量,所以需要给这些属性和方法添加修饰符public。
于是Chile类就变成了这样
class Child
{
//定义字段
public string _name;
public string _sex;
public int _age;
public void Playball()//踢足球方法
{
Console.WriteLine("我是C罗,啊哈哈哈哈哈哈!!!");
}
}
但是此时,如果我们在主程序中输入:
xiaoming._sex = "男孩";
xiaoming._sex = "女孩";
这是后男孩就变成了女孩,虽然代码不会报错,但是我们的逻辑会出现很大的错误,因此我们需要对属性进行封装。
定义:①隐藏对象的信息 ②留出访问的接口(现实生活中的ATM机就是一个很好的封装的例子,我们需要插入银行卡才能在ATM机中取钱。我们不能直接看见钱,所以说这是隐藏对象的信息;我们插入银行可能取出钱,这叫做留出访问的接口)
在C#中,我们通常使用属性堆字段进行封装
get和set分别是两个访问器,get读取_sex的值,set修改_sex的值
如果想更好的进行保护,我们可以不写set的值,这样Sex就成了只读属性
这样小朋友就不怕随便被改变性别了,于是Child类就变成了
class Child
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private string sex;
public string Sex
{
get { return sex; }
set { sex = value; }
}
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
}
主程序也相应作出了改变,访问字段的代码都变成了访问属性
static void Main(string[] args)
{
//实例化一个Child
Child xiaoming = new Child();
//给属性赋值
xiaoming.Name = "小明";
xiaoming.Age = 12;
xiaoming.Sex = "男孩";
//输出属性的值
Console.WriteLine("我是个小{0},我叫{1},我今年{2}岁。",xiaoming.Sex,xiaoming.Name,xiaoming.Age);
Console.ReadKey();
}
我们还可以对属性进行一定的保护,如果输入不可能的值那么就不会进行赋值,对于年龄我们就可以这样,因为是小明,所以如果输入5-10岁之外的值就不会有作用,这个方法同样适用于其他属性的保护。
private int age;
public int Age
{
get { return age; }
set
{
if (value < 10 && value > 5)//对值进行保护
age = value;
}
}
方法:对象的行为
方法的两个步骤:1.定义方法 2.调用方法
PlayBall方法在Child类中的定义
public void Playball()//方法的声明
{
//方法体 方法的实现
Console.WriteLine("我是小C罗,啊哈哈哈哈哈哈!!!");
}
EatSugar方法在主程序中调用
public void EatSugar(string sugar)
{
if (sugar == "水果糖")
{
Console.WriteLine("我最喜欢水果糖了!!");
}
else
{
Console.WriteLine("我不喜欢这种糖!!");
}
}
在主程序中的调用就会有所区别
xiaoming.PlayBall();
xiaoming.EatSugar("水果糖");
方法中定义的sugar是形参,调用中的"水果糖"是实参,程序运行,会把实参的值赋给形参,然后再向下运行
我们可以再重新写一个同名的方法,上一个方法是吃什么糖,我们再写一个限制吃糖数量的方法,这个方法只有一个参数数量
public void EatSugar(int Count)
{
if (Count > 3)//数量限制
{
Console.WriteLine("吃糖太多,不能吃了!!");
}else
{
Console.WriteLine("没事没事,吃吧!!");
}
}
需要注意的一点是方法重载的数据类型一定要不同,如果我们想把上面两个方法合起来的话直接把方法合起来便可
public void EatSugar(string sugar, intCount)
{
if (sugar == "水果糖")
{
Console.WriteLine("我最喜欢水果糖了!!");
}
else
{
Console.WriteLine("我不喜欢这种糖!!");
}
if (Count > 3)
{
Console.WriteLine("吃糖太多,不能吃了!!");
}
else
{
Console.WriteLine("没事没事,吃吧!!");
}
}
调用则变成了
xiaoming.EatSugar("水果糖",2);//水果糖,吃两块
return可以提前结束方法的调用,同时也可以当作返回值来使用,使他返回一个值来结束方法调用
小明也不小了,所以他需要学算术了,那么就要给他写一个算数的方法
public void Add(int num1,int num2)
{
int sum = num1 + num2;
Console.WriteLine(sum);
}
这个方法我们可以算数两个数的值,但是这个方法是一个没有定义返回值的方法,所以声明就是void。那么就要对其进行更改,同时使用了return返回值的使用,返回什么类型的值,就把void改成什么类型。算数的方法只进行算数操作,而不输出内容,所以我们应该将方法进行修改
public int Add(int num1,int num2)
{
int sum = num1 + num2;
return sum;
}
这样我们就可以只讲这个方法做一个算数的功能,也遵守了设计模式的单一职责原则
Child xiaoming = new Child();
这句话中的new Child()就是调用构造方法,括号里面没有东西,说明这个方法是无参的方法
构造方法的作用是为属性赋值。如果没有显示定义构造方法,那么就会有一个默认的无参的构造方法,但是如果定义了有参的构造方法,那么就默认的构造方法就没有了。调用构造方法只能使用new 方法名()。构造方法通常声明为public,没有返回值类型,而且名字需要与类名相同。
public Child(string name,string sex,intage)
{
Name = name;
Sex = sex;
Age = age;
}
我们需要将方法与类名重名进行重写,然后再将参数的值传给属性进行赋值。如果某个字段没有写成属性,那我们也可以直接把值传到字段当中直接赋值,效果相同。
this关键字的作用主要是区别字段和参数,如果字段和参数同名,我们可以写成this.sex = sex;,这句话的含义和Sex = sex;是一模一样的,只不过一个是直接将值付给了字段,另一个是先把值赋给了属性,再赋给字段
如果我们只知道这个小孩的名字和性别,而不知道年龄,上面的构造方法就不适用,所以说我们就要重新构造一个方法,让我们在调用方法的时候可以进行选择
public Child(string name, string sex)
{
Name = name;
Sex = sex;
}
这样,我们在调用的时候编译器就会自动的提示选用哪一个方法重载
Child xiaohong = new Child() {Name= "小红" , Sex = "女孩" };
这样也是可以进行赋值,相当于是对无参方法的操作