是否可以从指向子类对象的父类类型引用变量访问不在父类中的子类成员

本文关键字:父类 子类 访问 变量 成员 引用 类型 对象 是否 | 更新日期: 2023-09-27 18:27:39

根据我的理解,如果我有一个指向子类对象的父类类型引用变量:

ParentClass obj= new ChildClass();
obj.OnlyMembersThatHavebeenDerivedFromParentAreAvailable// am i wrong? 

在下面的例子中,我点击这里我应该无法访问年薪

派生类:

 public class FullTimeEmployee : Employee
    {
        public int AnnualSalary { get; set; }
    }

派生类:

public class PartTimeEmployee : Employee
    {
        public int HourlyPay { get; set; }
        public int HoursWorked { get; set; }
    }

父类

 public class Employee
    {
        private int _id;
        private string _name;
        private string _gender;
        private DateTime _dateOfBirth;
        [DataMember(Order = 1)]
        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }
        [DataMember(Order = 2)]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        [DataMember(Order = 3)]
        public string Gender
        {
            get { return _gender; }
            set { _gender = value; }
        }
        [DataMember(Order = 4)]
        public DateTime DateOfBirth
        {
            get { return _dateOfBirth; }
            set { _dateOfBirth = value; }
        }
        [DataMember(Order = 5)]
        public EmployeeType Type { get; set; }
    }

以下代码如何有效?:

Employee employee = null;
 employee = new FullTimeEmployee
                        {
                            Id = Convert.ToInt32(reader["Id"]),
                            Name = reader["Name"].ToString(),
                            Gender = reader["Gender"].ToString(),
                            DateOfBirth = Convert.ToDateTime(reader["DateOfBirth"]),
                            Type = EmployeeType.FullTimeEmployee,
                            AnnualSalary = Convert.ToInt32(reader["AnnualSalary"]) // how is AnnualSalary available here? 
                        };

是否可以从指向子类对象的父类类型引用变量访问不在父类中的子类成员

你是对的,你不能写:

employee.AnnualSalary = 1234;

但事实并非如此
您只是使用对象初始值设定项来初始化FullTimeEmployee对象(您可以访问所有公共字段/属性)
基本上你正在做以下事情:

FullTimeEmployee employeeTemp = new FullTimeEmployee();
employeeTemp .AnnualSalary =2000;
Employee employee =employeeTemp;

更新

我认为不能将父类对象类型转换为子类对象,因为孩子可以做父母能做的一切,反之亦然不是真的。

再一次你是对的
再说一遍,这不是你的情况
方法的返回类型可能是Employee,但实际返回的对象可能是其他对象(派生类)
在这种情况下,可以安全地将对象强制转换为派生类型
检查以下示例

namespace CastExample
{
  class Program
  {
    static void Main(string[] args)
    {
        Employee emp = GetEmployee();
        FullTimeEmployee full = (FullTimeEmployee)emp;
        System.Console.WriteLine(full.AnnualSalary);
        PartTimeEmployee part = (PartTimeEmployee)emp;//InvalidCastException
        System.Console.ReadLine();
    }
    static Employee GetEmployee()
    {
        return new FullTimeEmployee() { Name = "George", AnnualSalary = 1234   };
    }
  }
  public class Employee
  {
     public string Name;
  }
  public class FullTimeEmployee : Employee
  {
     public int AnnualSalary { get; set; }
  }
  public class PartTimeEmployee : Employee
  {
      public int HourlyPay { get; set; }
      public int HoursWorked { get; set; }
  }
}

他也可以访问私人财产??

是的,您可以使用反射访问私有字段
用Reflection找到一个私人领域
如何获取C#中私有字段的值
c#使用反射从派生类中获取私有成员变量

检查此项:为什么反射可以访问C#中类的受保护/私有成员
@Marc Gravell的回答解释了为什么你可以这样做,但要特别注意@Tamas Czinege的回答(我在这里再次引用)

成员可访问性不是一项安全功能。它是为了保护程序员反对自己。它有助于实施封装,但它决不是一个安全特性。