2009-09-13 21 views
3

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

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

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

+0

Если вы не хотите, чтобы свойства были доступны в производных классах, то почему они вообще определяют их в базовом классе? –

+0

Поскольку все свойства базового класса используются по крайней мере одним из четырех производных классов, но не для всех. Что я думаю, имеет 4 интерфейса для каждого из свойств. Затем производные классы могут выбирать интерфейсы, которые определяют необходимые ему свойства. – JMS

+0

@ JMs: Как отмечали другие люди, похоже, что дизайн должен быть другим, но у меня слишком мало информации, чтобы можно было предположить, что это должно быть. –

ответ

9

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

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

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

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

2

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

//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;} 
} 
0

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

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

1

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

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

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

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

+0

Да, это тот подход, о котором я думал, когда писал этот вопрос. Спасибо за разъяснения. – JMS

1

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

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. Как я уже сказал, он использует отражение и кастинг, но может сделать объектные модели очень элегантными при работе с базовыми классами.

Смежные вопросы