#c#
#c#
Вопрос:
Так вы добираетесь до свойств моего абстрактного класса?
public interface IMyObj(
void myMethod();
)
public abstract class MyObjBase
(
public string myProperty{get; set;}
)
public class myObj : MyObjBase, IMyObj
(
)
public void SomeMethod(IMyObj myobj)
{
// is there another way to do this, seems awkward
(myobj as myobjBase).myProperty = "value";
}
Ответ №1:
Поскольку myProperty
объявлен общедоступным, вы можете просто использовать его, как если бы он был локальным в производном классе, вам не нужно приводить к типу базового класса.
Где вам нужно было бы выполнить приведение, так это если вы объявили его как virtual
в базовом классе и переопределили его в производном классе, тогда вам нужно быть явным, если вы хотите вызвать базовую версию.
Не имеет значения, реализует ли базовый класс интерфейс, а производный класс хочет вызвать эту версию — она по-прежнему объявлена общедоступной ( protected
это тоже сработало бы), и нет переопределения, превосходящего ее.
Комментарии:
1. что, если метод, в котором находится код, выглядит следующим образом: public void someMethod(IMyObj myObj){…}. Intellisense не отображается для myObj
2. @rod, я расширил свой ответ. Убедитесь, что ваш производный класс включил пространство имен, содержащее определение интерфейса, и что ваша IDE не является pig. Кроме того, вам не нужно повторно реализовывать интерфейс в производном классе — просто сделайте реализацию в базовом классе виртуальной или абстрактной и переопределите ее в производном классе.
Ответ №2:
Тип вашего параметра должен быть типа «myObj» (поскольку класс реализует как интерфейс, так и абстрактный класс), если вы хотите получить доступ как к интерфейсным, так и к абстрактным членам класса. Ваш intellisense справедливо сообщает вам, что если вы передаете интерфейс, он ожидает любые производные классы, которые реализуют этот интерфейс, но не имеет возможности определить, какие другие абстрактные классы или интерфейсы вы реализуете. Я бы предположил, что:
public interface IMyObj
{
void myMethod();
}
public abstract class MyObjBase
{
public string myProperty { get; set; }
}
public class myObj : MyObjBase,IMyObj
{
public void myMethod()
{ }
}
public void SomeMethod(myObj myobj)
{
myobj.myProperty = "value";
}
Ответ №3:
Предполагая, как в вашем примере, что myobj
это экземпляр IMyObj
, вам действительно нужно было бы привести myobj
для ссылки myProperty
. Это потому, что экземпляр IMyObj
ничего не знает о членах классов MyObjBase
или MyObj
. Хотя это довольно странная вещь, и, вероятно, указывает на ошибку проектирования, потому что код, которому нужен IMyObj
интерфейс, на самом деле не должен знать, каков тип экземпляра объекта. Если вы хотите получить доступ к myProperty
из экземпляра IMyObj
, это довольно хороший признак того, что свойство должно быть определено в самом интерфейсе.
Однако, чтобы понять, как будет работать приведение типов в вашем примере, обратите внимание, что вы могли бы привести к либо базовому, либо производному классу:
MyObjBase asBase = myobj as MyObjBase;
MyObj asDerived = myobj as MyObj;
asBase.myProperty = "Hello ";
asDerived.myProperty = "World"; // refers to the same property as previous line
Если объединить последние два, получится:
string x = asBase.myProperty asDerived.myProperty; // x = "WorldWorld"
Теперь предположим, что у вас есть пара определений свойств virtual / override, например:
public virtual string myProperty { get; set; } // in MyObjBase
public override string myProperty { get; set; } // in MyObj
Тогда оба asBase.myProperty
и asDerived.myProperty
по-прежнему ссылаются на одно и то же свойство, но теперь оно myProperty
принадлежит производному классу. Фактически, учитывая экземпляр myobj
, нет никакого способа получить доступ к myProperty
базовому классу (кроме как через отражение). Более того, учитывая myobj
, код внутри самого базового класса больше не будет ссылаться на свой собственный myProperty
. Единственным кодом, который может получить доступ к свойству базового класса, является некоторый метод (или конструктор) в производном классе.
Например:
class MyObjBase
{
public virtual string myProperty { get; set; }
public void Foo()
{
myProperty = "something"; // refers to derived class property, if
// it overrides myProperty
}
...
}
class MyObj: MyObjBase, IMyObj
{
public override string myProperty { get; set; }
public string Bar()
{
base.myProperty = "Hello ";
myProperty = "World";
return base.myProperty myProperty; // returns "Hello World"
}
...
}