做的笔记,具体请参考https://learn.microsoft.com/zh-cn/dotnet/csharp/fundamentals/tutorials/inheritance
本文只是对教程中的例子进行实践。
一.继承
1.1 保护级别
1.1.1 Compiler Error CS0122
namespace Classes;
//只有在基类中嵌套的派生类中,私有成员才可见
public class A
{
private int _value = 10;
public class B : A
{
public int GetValue()
{
Console.WriteLine("--------B--------");
return _value;
}
}
}
public class C : A
{
public int GetValue()
{
//在这里会报错Compiler Error CS0122,
// CS0122:“"A._value" 不可访问,因为它具有一定的保护级别
return _value;
}
}
Compiler Error CS0122 | Microsoft Learn
此错误可以参考上面的链接
1.1.2 只有在基类中嵌套的派生类中,私有成员才可见。
namespace Classes;
//只有在基类中嵌套的派生类中,私有成员才可见
public class A
{
private int _value = 10;
public class B : A
{
public int GetValue()
{
Console.WriteLine("--------B--------");
return _value;
}
}
}
public class AccessExample
{
public static void Main(string[] args)
{
//A.B 是派生自 A 的嵌套类,而 C 则派生自 A。 私有 A._value 字段在 A.B 中可见。
var b = new A.B();
Console.WriteLine(b.GetValue());
}
}
// The example displays the following output:
// 10
1.2 受保护成员仅在派生类中可见。
namespace Classes;
//只有在基类中嵌套的派生类中,私有成员才可见
public class A
{
protected int _value = 10;
public class B : A
{
public int GetValue()
{
Console.WriteLine("--------B--------");
return _value;
}
}
}
public class C : A
{
public int GetValue()
{
Console.WriteLine("--------C--------");
return _value;
}
}
public class AccessExample
{
public static void Main(string[] args)
{
//A.B 是派生自 A 的嵌套类,而 C 则派生自 A。 私有 A._value 字段在 A.B 中可见。
var b = new A.B();
Console.WriteLine(b.GetValue());
var c = new C();
Console.WriteLine(c.GetValue());
}
}
// The example displays the following output:
//--------B--------
//10
//--------C--------
//10
总结
Public | 访问不受到限制 |
Protected | 允许本类以及派生类进行访问 |
Internal | 访问仅限于当前程序集 |
Protected Internal | 允许本类或派生类访问,注意比Internal的范围广 |
Private | 仅允许当前类访问,派生类不能访问 |
1.2重写继承的成员
基类成员必须标记有 virtual 关键字,才能重写继承的成员。 默认情况下,基类成员没有 virtual
标记,因此无法被重写。 标记有 abstract 关键字的基类成员要求派生类必须重写它们。继承仅适用于类和接口。
1.3 隐式继承
namespace Classes
{
public class SimpleClass
{ }
}
namespace Classes;
using System.Reflection;
public class SimpleClassExample
{
public static void Main()
{
Type t = typeof(SimpleClass);
BindingFlags flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
MemberInfo[] members = t.GetMembers(flags);
Console.WriteLine($"Type {t.Name} has {members.Length} members: ");
//Type SimpleClass has 9 members:
foreach (MemberInfo member in members)
{
string access = "";
string stat = "";
var method = member as MethodBase;
if (method != null)
{
if (method.IsPublic)
access = " Public";
else if (method.IsPrivate)
access = " Private";
else if (method.IsFamily)
access = " Protected";
else if (method.IsAssembly)
access = " Internal";
else if (method.IsFamilyOrAssembly)
access = " Protected Internal ";
if (method.IsStatic)
stat = " Static";
}
string output = $"{member.Name} ({member.MemberType}): {access}{stat}, Declared by {member.DeclaringType}";
Console.WriteLine(output);
//公共 GetType 方法:返回表示 SimpleClass 类型的 Type 对象。
//GetType(Method): Public, Declared by System.Object
//受保护 MemberwiseClone 方法:创建当前对象的浅表复制。
//MemberwiseClone(Method): Protected, Declared by System.Object
//受保护 Finalize 方法:用于在垃圾回收器回收对象的内存之前释放非托管资源。
//Finalize(Method): Protected, Declared by System.Object
//公共 ToString 方法将 SimpleClass 对象转换为字符串表示形式,返回完全限定的类型名称。 在这种情况下,ToString 方法返回字符串“SimpleClass”。
//ToString(Method): Public, Declared by System.Object
//公共实例 Equals(Object) 方法、公共静态 Equals(Object, Object) 方法和公共静态 ReferenceEquals(Object, Object) 方法。 默认情况下,这三个方法测试的是引用相等性;也就是说,两个对象变量必须引用同一个对象,才算相等。
//Equals(Method): Public, Declared by System.Object
//Equals(Method): Public Static, Declared by System.Object
//ReferenceEquals(Method): Public Static, Declared by System.Object
//公共GetHashCode 方法:计算允许在经哈希处理的集合中使用类型实例的值。
//GetHashCode(Method): Public, Declared by System.Object
//.ctor(Constructor): Public, Declared by Classes.SimpleClass
}
}
}
从上面的例子中我们可以看到,
.NET 类型系统中的所有类型除了可以通过单一继承进行继承之外,还可以隐式继承自 Object 或其派生的类型。 Object 的常用功能可用于任何类型。
然后可以使用反射(便于检查类型的元数据,从而获取此类型的相关信息),获取 SimpleClass
类型的成员列表。 尽管没有在 SimpleClass
类中定义任何成员,但示例输出表明它实际上有九个成员。 这些成员的其中之一是由 C# 编译器自动为 SimpleClass
类型提供的无参数(或默认)构造函数。 剩余八个是 Object(.NET 类型系统中的所有类和接口最终隐式继承自的类型)的成员。
1.3.1 隐式继承例子
下面的例子,用来隐式继承的toString()方法
namespace Classes
{
public class EmptyClass
{ }
}
namespace Classes;
using System.Reflection;
public class SimpleClassExample
{
public static void Main()
{
EmptyClass sc = new();
Console.WriteLine(sc.ToString());
//Classes.EmptyClass
}
}
上面例子调用 SimpleClass
从 Object 继承而来的 SimpleClass.ToString
方法。
下表列出了可以在 C# 中创建的各种类型及其隐式继承自的类型。 每个基类型通过继承向隐式派生的类型提供一组不同的成员。
类型类别 | 隐式继承自 |
---|---|
class | Object |
struct | ValueType, Object |
enum | Enum, ValueType, Object |
delegate | MulticastDelegate, Delegate, Object |