1.6C#语言基础-类和结构
类
- 对象 =算法+数据结构
- 程序=对象+对象+...
- 类是属性和方法的集合
类的几点特性
-
封装:属性和方法的封装
-
继承:通过继承,继承父类属性和方法,并拓展自身方法和属性
-
多态:同一方法的不同实现
学习好反射,可以写出很厉害的代码
属性
- 类的成员,变量
- 属性不能作为ref或out参数传递
- get访问器用来获取属性值
- set访问器用来设置值
- 通过 对象.属性名 来访问和设置
类的两种形式
- 在公共语言运行库的基础库中定义的属性
将SystemRdflection.TypeAttributes.Serializable用于自定义类,一便使该类中的成员可以序列化
[System.Serializable]
public class MyClass
{}
- 自定义属性
get/set访问器使用
public class Date
{
private int Day=7;
public int day
{
get{return Day;}
set{
if(value>0&&value<8)
{
Day=value;
}
}
}
}
get访问器必须返回值,类型和属性的类型保持一致,set返回值为void ,使用value隐式参数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StudyClass
{
class MyClass
{
private string id = "";
private string name = "";
/// <summary>
/// 定义id属性可读可写
/// </summary>
public string ID
{
get
{
return id;
}
set
{
id = value;
}
}
/// <summary>
/// 定义属性name 可读可写
/// </summary>
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
class Program
{
static void Main(string[] args)
{
//创建一个对象
MyClass c = new MyClass();
c.ID = "10001";
c.Name = "xiaoming";
Console.WriteLine("id:" + c.ID + "\n" + "name:" + c.Name);
}
}
}
类的方法
-
必须指定修饰符,常用的有4个访问修饰符:private、public、protected、internal,声明修饰符8个:partial,new,static,virtual,override,sealed,abstract,eternal
-
指定返回值,可有参数
4个访问修饰符
访问修饰符 | 说明 |
---|---|
private | 私有模式,只能被自己访问 |
public | 公共模式,访问不受限制 |
protected | 保护模式,类本身和该类的派生类可访问 |
internal | 同一程序集才能访问 |
8个声明修饰符
声明修饰符 | 说明 |
---|---|
partial | 在整个同一程序中定义分部类和结构 |
new | 从基类成员隐藏继承的成员 |
static | 声明属于类本身,不属于特定对象成员 |
virtual | 在派生的类中可以重写的方法或者访问器 |
override | 提供从基类继承的虚拟成员的新实现 |
sealed | 指定类不能被继承 |
abstract | 指定某个类只能式其他类的基类 |
extern | 指示在外部实现的方法 |
声明方法需要遵循的规则
- 声明最多包含 static,virtual ,override修饰符中的一个
- 声明最多包含 new 和 override的一个
- 使用了abstract,不能再包含static ,virtual,sealed 或extern
- 使用了private,不能再包含virtual,override,abstract
- 使用了sealed,不能包含override
静态方法
- 静态方法不能引用this
- 静态方法使用static声明
- 静态方法属于类本身
public static int Add(int x, int y)
{
return x+y;
}
非静态方法
- 非静态方法可以通过this来调用
方法重载
方法名称一样,返回值,参数个数、参数类型,参数顺序,只要其中一个不同即可
public static int Add(int x,int y)
{
return x + y;
}
public double Add(int x,double y)
{
return x + y;
}
public int Add(int x,int y, int z)
{
return x + y + z;
}
结构
- 结构式值类型
- 用来封装一组相关变量
- 向方法中传递结构时,结构是通过值传递的方式传递
- 结构的实例可以不使用new运算符
- 结构可以声明构造函数,必须带参数才行
- 结构不能继承,所有的结构都是直接结成System.ValueType,System.ValueType继承Sytem.Object
- 结构可以实现接口
- 在结构中初始化实例字段是错误的
由于结构的副本由编译器自动创建和销毁,因此不需要使用默认构造函数和析构函数。实际上编译器通过为所有字段赋予默认值来实现默认构造函数
结构的定义
结构修饰符 struct 结构名
{}
//demo
public struct Rect
{
public double width;
public double height;
public double Area()
{
return width*height;
}
}
static void Main(string[] args)
{
Rect rect;
rect.width = 5;
rect.height = 3;
Console.WriteLine("面积为:", rect.Area());
}
构造函数 和析构函数
- 构造函数用来初始化,实例化时调用,构造函数和类命相同
- 析构函数用来资源回收处理,实例销毁时调用,析构函数在类命前加入~
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StudyClass
{
class Program
{
public int x = 3;
public int y = 5;
public int z = 0;
public Program()
{
z = x + y;//构造函数中初始化z
}
~Program()
{
Console.WriteLine("执行了析构函数");
}
static void Main(string[] args)
{
Program prog = new Program();
Console.WriteLine(prog.z);
}
}
}
//结果输出
8
执行了析构函数
不带参数的钩函数是默认构造函数,一个类中只能有一个析构函数
继承
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StudyClass
{
class MyClass1
{
private int x = 0;
private int y = 0;
public int X
{
get { return x; }
set { x = value; }
}
public int Y
{
get { return y; }
set { y = value; }
}
public int Add1()
{
return X + Y;
}
}
class MyClass2:MyClass1
{
private int z= 0;
public int Z
{
get { return z; }
set { z = value; }
}
public int Add2()
{
return X + Y+Z;
}
}
class Program
{
static void Main(string[] args)
{
MyClass1 c1 = new MyClass1();
MyClass2 c2 = new MyClass2();
c1.X = 3;
c1.Y = 5;
c2.X = 4;
c2.Y = 6;
c2.Z = 6;
Console.WriteLine(c1.Add1());
Console.WriteLine(c2.Add1());
Console.WriteLine(c2.Add2());
}
}
}
//结果输出
8
10
16
请按任意键继续. . .
在子类中重写基类中的虚方法,可以使用base.方法名调用基类的虚方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StudyClass
{
class MyClass1
{
public virtual int Add(int x,int y)
{
return x+y;
}
}
class MyClass2:MyClass1
{
public int z = 0;
public int Z
{
get { return z; }
set { z = value; }
}
public override int Add(int x, int y)
{
return base.Add(x,y)+z;
}
}
class Program
{
static void Main(string[] args)
{
MyClass2 c = new MyClass2();
c.Z = 5;
Console.WriteLine(c.Add(4, 6));
}
}
}
//结果输出
15
请按任意键继续. . .
多继承需要使用接口,c#只支持单继承,继承的多个接口禁用逗号隔开
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StudyClass
{
interface IPeople
{
string Name
{
get;
set;
}
string Sex
{
get;
set;
}
}
class MyClass
{
public void Show()
{
Console.WriteLine("个人信息:");
}
}
class Program:MyClass,IPeople
{
string name = "";
string sex = "";
//继承了接口,必须把接口中访问器完善
public string Name
{
get { return name; }
set { name = value; }
}
public string Sex
{
get { return sex; }
set { sex = value; }
}
static void Main(string[] args)
{
Program prog = new Program();
IPeople ipeople = prog;
ipeople.Name = "XIAOMING";
ipeople.Sex = "男";
prog.Show();
Console.WriteLine(ipeople.Name + " " + ipeople.Sex);
}
}
}
多态
- 一个接口,多种方法
- 子类重写基类的虚方法
子类继承基类的所有方法字段,如果想要改变基类的数据和行为,有两种方式:
- 新的派生成成员替换基类成员,或者重写基类的方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StudyClass
{
class MyClass1
{
private int x = 0;
private int y = 0;
public int X
{
get
{
return x;
}
set { x = value; }
}
public int Y
{
get { return y; }
set { y = value; }
}
public virtual int Add()
{
return X + Y;
}
}
class MyClass2:MyClass1
{
public override int Add()
{
int x=5;
int y = 7;
return x + y;
}
}
class Program
{
static void Main(string[] args)
{
MyClass2 c2 = new MyClass2();
MyClass1 c1 = (MyClass1)c2;
c1.X = 9;
c2.Y = 20;
Console.WriteLine(c2.Add());//调用子类的方法
Console.WriteLine(c1.Add());//调用子类的方法
}
}
}
- 新的拍成成员替换基类的成员,使用new,如果基类定义了一个方法,字段,这new关键字用于在子类创建该方法字段的新定义
class MyClass2:MyClass1
{
public new int Add()
{
int x=5;
int y = 7;
return x + y;
}
}