私有成员是不是在 C# 中继承?

Posted

技术标签:

【中文标题】私有成员是不是在 C# 中继承?【英文标题】:Are private members inherited in C#?私有成员是否在 C# 中继承? 【发布时间】:2011-02-26 09:46:30 【问题描述】:

刚刚看到一个教程说:

Class Dog

  private string Name;

Class SuperDog:Dog

 private string Mood;

然后有一个 UML 显示 SuperDog 也将继承 Name。我试过了,但对我来说似乎只有公共成员是继承的。至少我不能访问 Name 除非它被声明为 public。

【问题讨论】:

@Tim Goodman:我假设您的意思是“如果它们可访问”而不是“如果它们被继承”。 派生类继承其基类的成员,无论访问说明符可能是什么。后者仅影响可以访问它们的人。 struct A private: //protected: //public: int x; ; struct B : A private: int x; ; int main() std::cout << sizeof(A) << '\n'; // 4 on my machine std::cout << sizeof(B) << '\n'; // 8 on my machine std::cout << '\n'; 【参考方案1】:

派生类可以访问 公共、受保护、内部和 受保护的基地内部成员 班级。即使派生类 继承基的私有成员 类,它不能访问这些成员。 但是,所有这些私人成员都是 仍然存在于派生类中,并且 可以做和他们一样的工作 基类本身。例如, 假设一个受保护的基类 方法访问私有字段。那 字段必须存在于派生的 为了继承基类的类 类方法才能正常工作。

发件人:http://msdn.microsoft.com/en-us/library/ms173149.aspx

所以,从技术上讲,是的,但实际上,不是。

【讨论】:

我总是将文档用作实际的“合同”,但作为一个兴趣点,.NET Reflection API 似乎在这一点上并不一致。如果您尝试使用derivedType.GetField("f", BindingFlags.Instance | BindingFlags.NonPublic) 从派生类中提取私有字段,您将一无所获,即使技术上应该返回所有继承的成员。因此,即使它在技术上必须存在,但在后台,运行时的所有相关部分都将它视为它实际上并不存在。 @Aaronaught:如果您自己走上继承树,似乎只能使用反射访问私有成员。见***.com/questions/686482/… @0xA3:是的,我知道如何解决这个问题,我只是指出 API 似乎与文档所讲述的故事不同。就 API 而言,私有成员不会被继承。 @Aaronaught:那将是一个“设计决策”,几乎除了 MS 之外的每个人都将其称为“错误”。不过,这点很好,并且与发布的答案非常相关。 +1 乍一看,我会说:“不,它们是私人的!”不过很好的答案,因为再三考虑,使用方法或其他方法通过私有字段给出的行为是继承的。这意味着仅派生类型无权访问它们。不过差别很小!伟大的! =)【参考方案2】:

基类的一切都是 继承到派生类。成员 标记为私有的不可访问 出于完整性目的的派生类, 你是否需要制作它们 在派生类中可访问,标记 受保护的成员。

在继承上下文中有不同级别的成员可访问性。

public: 基类的所有公共成员都可以在派生类和派生类的实例中访问。

protected: 基类的所有受保护成员都可以在派生类中访问,而不能被派生类的实例访问。

protected internal: 基类的所有受保护内部成员都可以在派生类中访问,也可以访问在同一程序集中创建的派生类实例。

internal:基类的所有内部成员都可以在派生类中访问,也可以在同一个程序集中被派生类的实例访问。

private: 在派生类和派生类的实例中不能访问基类的私有成员。

private protected:类型或成员只能在其声明的程序集中、通过同一类中的代码或从该类派生的类型中访问。

【讨论】:

我认为你在protected internal 上的措辞不妥。 protected internal 基类成员对所有派生类可见并且对与基类相同的程序集中的所有类公开。【参考方案3】:

SuperDog 将继承 Name 字段,是的。

SuperDog 将进入该领域,因此没有实际用途(就 SuperDog 而言)。

【讨论】:

【参考方案4】:

私有成员可以在派生类中可见:(如果子类嵌套在基类中)

public class Person

    private string message;

    public override string ToString()
    
        return message;
    

    public static Person CreateEmployee()
    
        return new Employee();
    

    class Employee : Person
    
        public Employee()
        
            this.message = "I inherit private members!";
        
    

该示例的功劳归于KodefuGuru in this thread at MSDN。

【讨论】:

【参考方案5】:

是的,尽管继承人无法访问该成员。

如果您这样他们将能够访问它,请将其声明为受保护

【讨论】:

【参考方案6】:

不,他们不是。

protected 修饰符可以使字段对派生类可用,但从维护的角度来看,这通常被认为是一个坏主意。您应该改用受保护的属性。

【讨论】:

确定???我相信它们是继承的——只是后代类无法访问。为什么?如果你将你的后代转换为基类会发生什么 - 如果基类的私有成员没有被继承......那会怎样?? -1 它们是继承的。它们只是对派生类不可见。这个问题似乎来自 OOP 的新手,不要通过混淆术语来混淆他们。 @Warren:再次阅读问题。他知道他不能访问基类的私有成员。他想知道他们是否在那里 嗯,是吗?这是一个有趣的问题,因为文档说它在那里,但没有实际的技术证明!考虑:class X 有私人成员Aclass Y 派生自 class Xtypeof(Y).GetField("A", Instance | NonPublic | FlattenHierarchy) 返回 null....typeof(Y).BaseType.GetField("A", Instance | NonPublic | FlattenHierarchy) 返回 A 的 FieldInfo。因此,-不-,就 .NET Framework 而言,这些字段不会被继承。它们仍然 - 仅 - 在基类中。 @Warren:“证明”很简单:编写一个带有私有成员的基类。创建一个使用私有成员的受保护或公共方法。在派生类的实例上调用该方法。尽管周围没有基类的实例,但它可以访问私有字段。【参考方案7】:

尝试使用关键字 protected,而不是 public/private:

http://msdn.microsoft.com/en-us/library/bcd5672a(VS.71).aspx

【讨论】:

【参考方案8】:

改用名称protectedpublic,这样就可以访问了。派生类不能访问私有成员

【讨论】:

【参考方案9】:

类的后代无法访问私有成员。

我不确定所有的访问修饰符,但在最基本的情况下,只有公共和受保护的成员是可访问的。

【讨论】:

私有以外的所有访问修饰符都被继承。 和@Cylon,请参阅最佳答案。继承!= 可访问。【参考方案10】:

是的,是继承的。 但是你不能访问它们,因为它们是私有的:)。

【讨论】:

【参考方案11】:

正如其他人所说,私有成员是继承的。成员访问是一个不同的主题,但从继承的角度来看并不完全脱节。重要的是要了解所有成员都是继承的,无论其访问修饰符如何,因为它会影响子类的大小。考虑以下代码。

public class Foo

  private int a;
  public int b;


public class Bar : Foo

  private int c;
  public int d;

Foo 将在堆上消耗 16 个字节。 4 个用于同步块,4 个用于类型信息(方法表),4 个用于int 变量,总共 12 个。另一方面,Bar 将消耗 24 个字节。同步块4个,类型信息(方法表)4个,继承自Fooint字段各4个,Bar中的int字段各4个,一共24个。

【讨论】:

【参考方案12】:

人们已经说过,但这里有一个示例说明为什么需要派生类中的私有字段:

class Program

    static void Main(string[] args)
    
        var r = new Random();

        foreach(var i in Enumerable.Range(0,100))            
            new Derived(r).Printer();            

        Console.Read();
    


public class Base

    private Random r;
    public Base(Random r)  this.r = r; 

    protected void Print()
    
        Console.WriteLine(r.Next(1, 10000));
    


public class Derived : Base

    public Derived(Random r) : base(r)  
    public void Printer()
    
        base.Print();
    

【讨论】:

【参考方案13】:

你说得对,派生类无法访问private 成员。

您应该创建成员protected 或使用基类的公共方法访问它们。

class Player

    protected string name;
    protected string type;

    public Player(string name,string type)
    
        Console.WriteLine("Player"+ this);
        this.name = name;
        this.type = type;
    
   public void introduce()
    
        Console.WriteLine("I am " + this.name + " I'm a " + this.type);
    


class Wizard : Player

    public Wizard(string name,string type):base(name,type)
    
        Console.WriteLine("Wizard"+ this);
      
    
    public void Play()
    
        //protected modifier made the name field available;
        Console.WriteLine("Yipeeee!!!!!"+ " "+ this.name);
        
        //on the other hand
        // we can make the name and type fields as private in the base class and access them using the public methods of the base class
        introduce();

    

【讨论】:

【参考方案14】:

是的,但是它们不可访问,因此您可以诚实地说它们不是继承的。但是是的,他们确实是

【讨论】:

不是一个具体的声明,直截了当,看起来更像是外交回答

以上是关于私有成员是不是在 C# 中继承?的主要内容,如果未能解决你的问题,请参考以下文章

C#中继承问题

在 C# 中继承泛型

如何在c#中继承非继承属性

C++中继承与多态

Java中 继承的概述与定义实例

java中继承的特点