Сокрытие свойств в производных классах C # - PullRequest
3 голосов
/ 13 сентября 2009

У меня есть четыре класса, которые имеют некоторое расположение четырех свойств. В настоящее время я установил базовый класс равным abstract с каждым свойством, помеченным как virtual. Затем в каждом из четырех производных классов я переопределяю свойства, которые он использует, и игнорирую остальные.

Проблема в том, что я все еще могу получить доступ ко всем свойствам в каждом из производных классов, независимо от того, переопределил ли я его из свойства abstract virtual в моем базовом классе.

У меня такое ощущение, что я подхожу к этому с неправильной точки зрения. Есть ли способ явно скрыть или заблокировать свойства, или есть лучший подход.

Ответы [ 5 ]

9 голосов
/ 13 сентября 2009

Я считаю, что вы должны переосмыслить иерархию наследования. Рассмотрим следующую эвристику:

Если два или более классов совместно используют только общие данные (без общего поведения), то эти общие данные должны быть помещены в класс, который будет содержаться в каждом классе совместного использования.

Если два или более классов имеют общие данные и поведение (т. Е. Методы), то каждый из этих классов должен наследоваться от общего базового класса, который захватывает эти данные и методы.

Если два или более классов совместно используют только общий интерфейс (т. Е. Сообщения, а не методы), то они должны наследовать от общего базового класса, только если они будут использоваться полиморфно.

2 голосов
/ 13 сентября 2009

Боюсь, что невозможно скрыть членов в производном классе (это противоречит правилам наследования). Для решения этой проблемы у вас может быть два уровня абстрактных классов. На первом уровне есть базовый класс со всеми членами, которые должен быть среди всех производных классов, на втором уровне вы можете иметь специальные классы только с членами, которые вы хотите наследовать от этого класса.

//Level1
public abstract class Employee
{
public string Name{get;set;}
public abstract double CalculateSalary();

}

//Level2
public abstract class CalssAEmployee:Employee
{
public int NumberOfWorkingHours{get;set;}

}

public abstract class ClassBEmployee:Employee
{
public int NumberOfSales{get;set;}
}
1 голос
/ 25 августа 2011

Если вы не возражаете против рефлексии и кастинга, вы можете попробовать что-то подобное, используя вспомогательные методы. В приведенном ниже примере предполагается, что существует базовый класс для заказов, который здесь не показан:

public abstract class Client : Entity
{
    public virtual string Name { get; set; }
    public virtual string  Comments { get; set; }
    public virtual string  Requirement { get; set; }
    public virtual string  Complaints { get; set; }
 }

public class GreatClient : Client
{
    public virtual List<GreatOrder>  Orders { get; set; }
}

public class WebClient : Client
{
    public virtual List<BadOrder> Orders { get; set; }
}

public static class ClientHelper
{
    public static IEnumerable<Order> GetOrders(this Client client)
    {
        var result = new Dictionary<Type, Func<Client>>
                         {
                             {typeof (GreatClient), () => { return ((GreatClient) client).Orders;}},
                             {typeof (WebClient), ()=> { return ((WebClient) client).Orders;}}
                         };

        return result[dto.GetType()].Invoke();
    }
}

//Client code
Client client = new WebClient();
client.GetOrders();

Друг показал мне этот маленький образец, спасибо Nap. Как я уже сказал, он использует отражение и приведение, но может сделать объектные модели очень элегантными при работе с базовыми классами.

1 голос
/ 13 сентября 2009

Вы не можете удалять / скрывать методы или свойства в производных классах, поскольку это противоречит принципу подстановки Лискова.

Вы можете переопределить свойства, чтобы выдавать исключения, но это не очень хороший дизайн.

В классе должны быть только те члены, которые действительно действительны в этом классе.

Может быть, вы хотите определить несколько интерфейсов, имеющих ваши свойства, и позволить каждому классу реализовывать необходимые вам интерфейсы.

0 голосов
/ 13 сентября 2009

Здесь есть пара правил.

если у вас есть абстрактный класс с виртуальными свойствами, он может быть защищенным или общедоступным, и это увидит внешний мир. Когда вы расширяете / наследуете этот класс, вы можете переопределить эти свойства, но не пометить их как закрытые. Private - единственный способ скрыть свойство от производного класса. Наличие частной собственности в абстрактном классе скрывает ее от детей. Но это явно не тот случай в вашем сценарии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...