目录
抽象类 和 抽象成员
抽象成员是一个被设计为被覆写的成员函数, 抽象成员有如下特征:
- 成员函数、属性、索引器、事件等都可以被声明为抽象成员。 字段 和常量不能不能声明为抽象成员。
- 必须用 abstract 修饰符修饰。
- 不能有实现代码块。 抽象成员的代码用分号表示。
抽象类只能被继承,不能创建抽象类的实例,抽象类的class 前面必须用 abstract 修饰符做前辍。
关于抽象成员 和 抽象类 应注意的有:
- 尽管抽象成员必须在派生类中用相应的成员覆写, 但不能把 virtual 修饰符附加到 abstract 修饰符上。
- 如果说在派生类中不实现抽象类中的抽象成员, 那么派生类也是个抽象类, 那么派生类的class 前面也要加上 abstract ,否则的话不用加。
- 任何派生自抽象类的类必须使用override关键字实现抽象类的所有抽象成员。否则的话,该类还是个抽象类。
namespace HelloWorld_Console
{
abstract class MyBase
{
public int Length = 10;
const int Count = 3;
public int Result()
{
return Length * Count;
}
abstract public void Print(string s);
abstract public int MyInt
{
get;set;
}
}
class MyClass : MyBase
{
public override void Print(string s)
{
WriteLine($"调用MyClass类中的Print 该函数,值为:{s}");
}
private int _MyInt;
public override int MyInt
{
set
{
_MyInt = value;
}
get
{
return _MyInt;
}
}
}
class SecondClass: MyClass
{
//这里如果不用override 关键字,那么使用new关键字 隐藏该类的基类中的同名函数
public override void Print(string s)
{
WriteLine($"调用SecondClass类中的Print 该函数,值为:{s}");
}
private int _MyInt;
public override int MyInt
{
set
{
_MyInt = value;
}
get
{
return _MyInt;
}
}
}
class Program
{
static void Main(string[] args)
{
// MyBase a = new MyBase(); 错误, 抽象类不可以创建实例
MyClass mc = new MyClass();
mc.Print("huangchengtao");
mc.MyInt = 28;
WriteLine($"输出MyClass 类 get属性的值:{ mc.MyInt}");
WriteLine($"输出基类中 Result 函数的值:{mc.Result()}");
WriteLine();
SecondClass mySecondClass = new SecondClass();
MyBase a = (MyBase)mySecondClass; //正确, 基类引用 派生类对象
a.Print("TAOTAO");
a.MyInt = 522;
WriteLine($"输出SecondClass 类 get属性的值:{ a.MyInt}");
WriteLine($"输出基类中 Result 函数的值:{a.Result()}");
ReadKey();
}
}
}
输出结果为:
调用MyClass类中的Print 该函数,值为:huangchengtao
输出MyClass 类 get属性的值:28
输出基类中 Result 函数的值:30
调用SecondClass类中的Print 该函数,值为:TAOTAO
输出SecondClass 类 get属性的值:522
输出基类中 Result 函数的值:30
成员访问修饰符
对类的可访问性 , 只有两种修饰符:
- internal 和 public
声明在类中的每个成员对系统的不同部分可见, 这依赖于类声明中指派给它的访问修饰符。private成员仅对同一类的其他成员可见, 而public成员对程序集外部的类也可见。
注意事项:
- 所有显式声明在类声明中的成员都是互相可见的,无论它们的访问性如何。
- 继承的成员不在派生类的声明中显式声明,所以,继承的成员对派生类的成员可以是可见的,也可以是不可见的。
- 必须对每个成员指定成员访问级别。如果不指定某个成员的访问级别,它的隐式访问级别为private.
- 成员不能比它的类有更高的可访问性。也就是说, 如果一个类的可访问性限于它所在的程序集,那么类的成员个体也不能从程序集的外部看到,无论它们的访问修饰符是什么, public也不例外。
- 类通过成员的访问修饰符指明了哪些成员可以被其他类访问。
- 公有类的public 成员对同一程序集 或 其它程序集的所有类可见的, 派生类甚至可以在其他程序中。
- 内部类的public 成员只对同一程序集的代码可见, 对其它程序集的所有类是不可见的。
- 任何类的private成员只对它自己的类(或嵌套类)的成员可见。
- 公有类的protected成员对它自己的类成员或者派生类类成员是可见的。 派生类甚至可以在其他程序中。
- 内部类的protected成员对它自己的类成员或者派生类类成员是可见的。 派生类不可以在其他程序中。
- internal 成员对同一程序集内部的任何类成员可见, 但对程序集外部的类不可见。
- 公有类的 protected internal 成员对相同程序集的类成员 或者继承该类的类成员是可见的。它对其它程序集中不继承该类的类不可见。
- 内部类的 protected internal 成员对相同程序集的类成员 或者继承该类的类成员是可见的(派生类不可以在其他程序中)。它对其它程序集中不继承该类的类不可见。
静态类
关于静态类要注意的有:
- 类本身必须标记为static
- 类的所有成员必须是静态的。
- 类可以有一个静态构造函数,但不能有实例构造函数, 不能创建该类的实例。
- 静态类是隐式密封的,也就说, 不能继承静态类。
- 静态类的常用方法是创建一个包含一组数学方法和值的数学库。
namespace HelloWorld_Console
{
static public class MyMath
{
public static float PI = 3.14F;
public static bool IsOdd(int x)
{
return (x % 2 == 1);
}
public static int Times(int x)
{
return 2 * x;
}
}
class Program
{
static void Main(string[] args)
{
int val = 3;
WriteLine($"输出IsOdd的值:{MyMath.IsOdd(val)}");
WriteLine($"输出Times的值:{MyMath.Times(val)}");
ReadKey();
}
}
}
输出结果为:
输出IsOdd的值:True
输出Times的值:6
sealed 密封类
在C#中,sealed关键字有两个作用:
当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承。意识就是说 sealed 类,只能是一个独立的类, 不能做别的类的基类
在下面的示例中,类 B 从类 A 继承,但是任何类都不能从类 B 继承。class A {} sealed class B : A {}
注意: 密封类中不能包含虚方法(Virtual)和抽象方法(abstract),因为在密封的类没有为派生类提供实现其虚方法和抽象方法的机会。