2014-12-04 3 views
0

Допустим, у меня есть класс:Как получить явные типы детей в собственности

class AbstractPerson{ 

AbstractAttribute attr {get; set;} 

} 

Теперь в детском классе AbstractPerson, я хочу использовать Аттрибут но, в частном случае, например, так:

class Pilot: AbstractPerson { 

... 
(attr as SpecialAttribute).pilotID; 
... 
} 

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

Таким образом, это не работает:

class Pilot: AbstractPerson { 
AbstractAttribute attr { 
get 
{ 
return (attr as SpecialAttribute); 
} 
set; 
} 

} 

даже возможно ли это?

*** Я знаю, что по соглашению «attr» должно быть в PascalCase, я просто забыл об этом примере. На самом деле Человек является Контроллером и Аттрем.

+0

Ну, вы возвращаете 'attr' как' SpecialAttribute', но поскольку свойство все еще имеет тип 'AbstractAttribute', вы вернетесь туда, откуда вы начали.У вас может быть свойство * different *, например 'SpecialAttribute attrSpecial {get {return attr as SpecialAttribute; }} ', а затем используйте это внутри' Pilot'. – Corak

+0

Да, ты прав. Я имею в виду наличие другого свойства, но тогда у меня не было бы свойства ONE, достаточного для двух вещей: действовать как особая вещь, но все же предоставить всю абстрактную вещь, которую она имеет. Я думаю, что решение дженериков лучше. Спасибо! – ruffy

ответ

1

Предполагая, что:

class SpecialAttribute : AbstractAttribute {} 

Вы можете использовать дженерики:

class AbstractPerson<T> 
    where T : AbstractAttribute 
{ 
    T attr {get; set;} 
} 

class Pilot: AbstractPerson<SpecialAttribute> 
{ 
    /* ... */ 
    void Foo() 
    { 
     // attr is a SpecialAttribute here 
     attr.PropertyOfSpecialAttribute = "bar"; 
    } 
} 

Обратите внимание, что вы злоупотребляя as оператора.
Если есть возможность, что attr не SpecialAttribute, чем asдолжен следовать нуль-проверка:

var foo = bar as Foo; 
if (foo != null) 
{ 
    // do something 
} 

В противном случае (если attrдолжен быть SpecialAttribute), вы обязательно литье под давлением:

var foo = (Foo)bar; 

to throw InvalidCastException, if тип не ожидается.

+0

Большое спасибо! – ruffy

1

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

class AbstractPerson 
{ 
    AbstractAttribute Attribute { get; set; } 
} 

class Pilot : AbstractPerson 
{ 
    PilotAttribute PilotAttribute 
    { 
     get { return (PilotAttribute)AbstractAttribute; } 
     set { AbstractAttribute = value; } 
    } 
} 

Естественно, этот подход требует, чтобы PilotAttribute на самом деле происходит из AbstractAttribute, то, что на самом деле не требуется в общем решении (если не вам особенно хочу, чтобы это было). Он также не обеспечивает уровень безопасности, который выполняет общее решение: AbstractAttribute все еще присутствует и ему может быть присвоено значение не PilotAttribute. Поэтому вам нужно быть осторожным, чтобы этого не делать (желательно, избегая использования базового атрибута при работе с экземплярами Pilot).

Также можно просто скрыть базу AbstractAttribute недвижимость с новой. Но я ненавижу сокрытие членов и ИМХО, что все, что здесь делает, делает код более запутанным.

+0

Да, вы правы. Спасибо за эту альтернативу! Я подумаю, когда это более практично! – ruffy

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