C#的继承
不像C++那样可以灵活的使用单重和多重继承,C#仅支持单重继承,中所有类都是从 Object 类继承而来的,Object 类中的属性和方法可以被用到任何类。
而若要使用多重继承则是通过接口来解决这一问题。
object类
object类是C#中所有类的根源,无论是系统预设的datetime类、math类,还是用户自己定义的类,都是由object类继承而来,这就意味着所有类都可以使用obj类中所含的方法和属性
obj类常用的方法
常用方法 | 描述 |
---|---|
Equals | 判断两个对象是否相等 |
GetHashCode | 获取哈希码 |
GetType | |
ToString |
Equals方法用于两个对象是否相等,包括引用对象,若相等为True
Equals (object ol, object o2); //静态方法
Equals (object o); //非静态方法
GetHashCode 方法返回当前 System.Object 的哈希代码,每个对象的哈希值都是固定的。
该方法不含有任何参数,并且不是静态方法,因此需要使用实例来调用该方法
Console.WriteLine(obj1.GetHashCode());
GetType方法用于获取对象type类型,返回值为 System.Type 类型。
class Program
{
static void Main(string[] args)
{
int i = 100;
string str = "abc";
Student stu = new Student();
Console.WriteLine(i.GetType());
Console.WriteLine(str.GetType());
Console.WriteLine(stu.GetType());
}
}
ToString方法用于返回对象实例的字符串
继承
C#使用的继承方式:
可能是由于只有单重继承的原因吧,所以父类前面不用加修饰符
访问修饰符 class ClassA:ClassB
{
//类成员
}
这区分于C++使用的继承
class ClassA:继承修饰符 Class B
{
//类成员
}
base关键字
base.func();
调用父类成员函数。
virtual
和C++中的virtual概念很类似,可以理解为重写父类中的属性和方法时使用
//修饰属性
public virtual 数据类型 属性名{get; set; }
//修饰方法
访问修饰符 virtual 返回值类型方法名
{
语句块;
}
子类在重写时加上修饰override
public override void Print()
{
base.Print ();
Console.WriteLine("专业:"+ Major);
Console.WriteLine("年级:"+ Grade);
}
abstract
abstract 关键字代表的是抽象的,使用该关键字能修饰类和方法,修饰的方法被称为抽象方法、修饰的类被称为抽象类。类似C++的虚基类,同样不能进行实例化
访问修饰符 abstract 方法返回值类型 方法名(参数列表);
抽象方法定义后面的“;”符号是必须保留的。需要注意的是,抽象方法必须定义在抽象类中。
在定义抽象类时,若使用 abstract 修饰类,将其放到 class 关键字的前面,语法形式如下。
访问修饰符 abstract class 类名
{
//类成员
}
sealed
声明密封类或密封方法,使用该关键字能修饰类或者类中的方法,修饰的类被称为密封类、修饰的方法被称为密封方法
密封方法必须出现在子类中,并且是子类重写的父类方法,即 sealed 关键字必须与 override 关键字一起使用
密封类不能被继承,密封方法不能被重写
构造器
和C++的构造函数类似,继承关系也几乎相同
在子类中若想调用父类构造器的话加 :base() 即可
多态
多态称为运行时多态,也就是在程序运行时自动让父类的实例调用子类中重写的 方法,它并不是在程序编译阶段完成的
实现多态必须满足:
- 子类在继承父类时必须有重写的父类的方法。
- 在调用重写的方法时,必须创建父类的对象指向子类(即子类转换成父类)
接口
接口就是用于实现像C++中的多重继承
用interface关键字定义接口
interface 接口名称
{
接口成员;
}
- 接口名称
通常是以 I 开头,再加上其他的单词构成。例如创建一个计算的接口,可以命名为 ICompute。 - 接口成员
接口中定义的成员与类中定义的成员类似。
接口中定义的成员必须满足以下要求。
- 接口中的成员不允许使用 public、private、protected、internal 访问修饰符。
- 接口中的成员不允许使用static、virtual、abstract、sealed 修饰符。
- 在接口中不能定义字段。
- 在接口中定义的方法不能包含方法体。
interface ICompute
{
int Id { get; set; }
string Name { get; set; }
void Total();
void Avg();
}
由于接口中的方法并没有具体的内容,直接调用接口中的方法没有任何意义
在 C# 语言中规定不能直接创建接口的实例,只能通过类实现接口中的方法
接口的实现
在类中实现一个接口时必须将接口中的所有成员都实现,否则该类必须声明为抽象类,并将接口中未实现的成员以抽象方式实现
class 类名 : 接口名
{
//类中的成员以及实现接口中的成员
}
隐式实现:
class ComputerMajor : ICompute
{
public int Id { get; set; } //隐式的实现接口中的属性
public string Name { get; set; } //隐式实现接口中的属性
public double English { get; set; }
public double Programming { get; set; }
public double Database { get; set; }
public void Avg() //隐式实现接口中的方法
{
double avg = (English + Programming + Database) / 3;
Console.WriteLine("平均分:" + avg);
}
public void Total()
{
double sum = English + Programming + Database;
Console.WriteLine("总分为:" + sum);
}
}
显示实现:
class ComputerMajor : ICompute
{
public double English { get; set; }
public double Programming { get; set; }
public double Database { get; set; }
int ICompute.Id { get; set; } //显示实现接口中的属性
string ICompute.Name { get; set; } //显示实现接口中的属性
void ICompute.Total() //显示实现接口中的方法
{
double sum = English + Programming + Database;
Console.WriteLine("总分数:" + sum);
}
void ICompute.Avg()
{
double avg = (English + Programming + Database) / 3;
Console.WriteLine("平均分为:" + avg);
}
}
在使用显式方式实现接口中的成员时,所有成员都会加上接口名称 ICompute 作为前缀,并且不加任何修饰符
接口实现多态
条件
- 定义接口并使用类实现了接口中的成员。
- 创建接口的实例指向不同的实现类对象。
interface IShape//接口Ishape
{
double Area { get; }
double X { get; set; }
double Y { get; set; }
string Color { get; set; }
void Draw();
}
class Rectangle :IShape
{
//为矩形的长和宽赋值
public Rectangle(double length,double width)
{
this.Length = length;
this.Width = width;
}
public double Length { get; set; }//定义长方形的长度
public double Width { get; set; }//定义长方形的宽度
public double Area
{
get
{
return Length * Width;//计算长方形面积
}
}
public string Color { get; set; }
public double X { get; set; }
public double Y { get; set; }
public void Draw()
{
Console.WriteLine("绘制图形如下:");
Console.WriteLine("在坐标 {0},{1} 的位置绘制面积为 {2} 颜色为 {3} 的矩形", X, Y, Area, Color);
}
}
class Circle : IShape
{
//为圆的半径赋值
public Circle(double radius)
{
this.Radius = radius;
}
public double Radius { get; set; }
public double Area
{
get
{
return Radius * Radius * 3.14;
}
}
public string Color { get; set; }
public double X { get; set; }
public double Y { get; set; }
public void Draw()
{
Console.WriteLine("绘制图形如下:");
Console.WriteLine("在坐标为 {0},{1} 的位置绘制面积为 {2} 颜色为 {3} 的圆形", X, Y, Area, Color);
}
}
主程序:
class Program
{
static void Main(string[] args)
{
IShape shape1 = new Rectangle(10, 20);
shape1.X = 100;
shape1.Y = 200;
shape1.Color = "红色";
shape1.Draw();
IShape shape2 = new Circle(10);
shape2.X = 300;
shape2.Y = 500;
shape2.Color = "蓝色";
shape2.Draw();
}
}