2015-12-20 2 views
0

Согласно моему пониманию, если у меня есть ссылочный переменная, указывающая тип родительского класса для объекта класса ребенок:Возможно ли получить доступ к элементам дочернего класса, которые не относятся к родительскому классу из ссылочной переменной типа родительского класса, указывающей на объект дочернего класса?

ParentClass obj= new ChildClass(); 

obj.OnlyMembersThatHavebeenDerivedFromParentAreAvailable// am i wrong? 

В приведенном ниже примере, который я взял из click here я не должен быть в состоянии получить доступ AnnualSalary

производный класс:

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? 
         }; 
+1

У вас возникли проблемы с этим? Скомпилирует ли он? –

+0

Я не воссоздал это в визуальной студии. Я смотрел видео-учебник из этого же блогера (использует тот же самый код, который находится в этом блоге), и он смог успешно скомпилировать и запустить его. Так что да, он компилируется. Но как получилось? – Arbaaz

ответ

2

Вы правы, вы не можете писать:

employee.AnnualSalary = 1234; 

Но это не ваш случай.
Вы используете инициализатор объекта для инициализации объекта FullTimeEmployee (у вас есть доступ ко всем общедоступным полям/свойствам).
В основном вы делаете следующее:

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

Update

Я думал, один не может напечатанный объект родительского класса для дочернего класса объекта, поскольку ребенок может делать все, что родитель может, но наоборот неправда.

Снова вы правы.
И еще раз это не ваше дело ...
Тип возвращаемого метода может быть 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; } 
    } 
} 

И он может получить доступ к частному свойству тоже ??

Да, вы можете получить доступ к частному полю с помощью отражения
Find a private field with Reflection?
How to get the value of private field in C#?
c# use reflection to get a private member variable from a derived class

Проверьте это: Why can reflection access protected/private member of class in C#?
ответ @Marc Gravell объясняет, почему вы можете это сделать, но обратить особое внимание на @Tamas Czinege (я цитирую его здесь снова)

Доступность элемента не является функцией безопасности. Он защищает программист от самого себя. Это помогает реализовать инкапсуляцию , но это отнюдь не функция безопасности.

+0

OH! Я получаю это сейчас. Проклятый синтаксис инициализатора! Btw просто чтобы убедиться, что мой метод возвращает этот объект 'employee'. Нет способа, чтобы вызывающий абонент мог получить доступ к Годовой системе? Присвоение ценности годовому «Салари» было бы напрасно в этом конкретном сценарии? – Arbaaz

+0

@Arbaaz Если ваш метод возвращает объект типа Employee, вызывающий абонент не может получить доступ к AnnualSalary, используя. но ** вызывающий может передать объект FullTimeEmployee, а затем получить доступ ко всем общедоступным свойствам класса FullTimeEmployee, включая AnnualSalary (он может очень легко получить доступ к частной собственности также ...) –

+0

Вы уверены? Я имею в виду, я думал, что нельзя подобрать объект родительского класса к объекту дочернего класса, так как ребенок может делать все, что может родитель, но наоборот не соответствует действительности. И он также может получить доступ к частной собственности? Как? Мне жаль, что это из-за контекста, но мне нужно знать, как это сделать. – Arbaaz