PS:注释和讲解全在代码中
1. 类的继承
C#继承特点
- C#派生类只能继承一个父类,可以通过接口来实现多重继承
- 继承是可以传递的,例如C从B派生,B又从A派生,那么C不仅继承了B中声明的成员,同样也继承了A中声明的成员
- 派生类是对基类的扩展,派生类可以添加新的成员,但不能移除已经继承的成员的定义
- 构造方法和析构方法不能被继承(不能继承,不过可以访问),除此之外其他成员能会被继承(当然更可以访问)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C4_程序设计
{
class Point //点类
{
public int x, y;
public Point() { x = y = -1; } //手写一个默认构造(重载方法)
//构造方法99%的情况下都是public,基本上只在单例模式下才使用private修饰
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
void Move(int dx, int dy)
{
x += dx;
y += dy;
}
public void Print()
{
Console.WriteLine("当前调用父类方法:点的坐标为{0},{1}", x, y);
}
}
class State: Point //和C++不一样,C#不支持多继承,也就是说一个类只能有最多一个父亲
{
public int col;
//public new int x;
/*
如果这里对父类的x进行隐藏,重新定义一个新的x,也就是声明public new int x;
那么输出结果将会变为
当前调用父类方法:点的坐标为5,6
当前调用子类方法:点的坐标为0,-1,点的颜色为0,价值为0
当前调用父类方法:点的坐标为-1,-1
当前调用父类方法:点的坐标为-1,-1
当前调用父类方法:点的坐标为-1,-1
*/
private double val;
public State() { }
public State(int x, int y, int col, double val)
: base(x, y) //调用父类的构造方法,如果没有调用,则默认为调用父类默认构造方法
{
this.col = col;
this.val = val;
this.x = x;
}
public double Val
{
get
{
return val;
}
set
{
if (value >= 100 || value <= 0)
val = -1;
else
val = value;
}
}
/*public void Print() //错误,该方法在父类中已经出现,必须使用关键字new进行隐藏
{
Console.WriteLine("当前调用子类方法:点的坐标为{0},{1},点的颜色为{2},价值为{3}", x, y, col, val);
}*/
public new void Print()
{
Console.WriteLine("当前调用子类方法:点的坐标为{0},{1},点的颜色为{2},价值为{3}", x, y, col, val);
}
}
class 类与继承
{
static void Main()
{
Point temp, fa = new Point(5, 6);
State son = new State();
fa.Print(); //当前调用父类方法:点的坐标为5,6
son.Print(); //当前调用子类方法:点的坐标为-1,-1,点的颜色为0,价值为0
((Point)son).Print(); //当前调用父类方法:点的坐标为-1,-1
temp = son;
temp.Print(); //当前调用父类方法:点的坐标为-1,-1
son.x = -155;
temp.Print(); //当前调用父类方法:点的坐标为-155,-1
//为什么修改son会影响temp呢?这里别忘了之前有提到过的,C#和C++的不同,temp和son指向的是同一堆空间
//其实不建议这么做
//son = temp;
//son = (State)fa; //这两个语句都错误,不允许将父类对象转换为子类对象
son = (State)temp; //正确,因为这个父类对象里面实际上装的是子类对象,所以可以转回子类对象,遵循里氏转换原则
}
}
}
程序类视图: