Приведение в C # с интерфейсами, чтобы иметь возможность использовать все функциональные возможности объекта - PullRequest
3 голосов
/ 08 ноября 2011

У меня возникла небольшая проблема с приведением моих объектов в C #, чтобы иметь возможность использовать дополнительные методы объекта, помимо тех, которые объявлены в интерфейсе.Ниже приведен простой пример того, о чем я говорю.

public interface IShape
{
    void Print();
}

public class Square : IShape
{
    #region IShape Members

    public void Print()
    {
        HttpContext.Current.Response.Write("Square Print Called"); 
    }   

    #endregion

    public void PrintMore()
    {
        HttpContext.Current.Response.Write("Square Print More Called"); 
    }        
}

Почему, когда этот код называется ниже, я не могу получить доступ к PrintMore ()?

IShape s = (Square)shape;
s.PrintMore() // This is not available. only Print() is. 

Любая помощь иобъяснение будет полезно?

Ответы [ 6 ]

5 голосов
/ 08 ноября 2011

Ваша переменная s по-прежнему имеет тип IShape. То, что вы использовали приведение при присвоении ему, не меняет тип в том, что касается компилятора. Вам нужно:

Square s = (Square) shape;
s.PrintMore();

Конечно, это будет работать, только если shape действительно равно a Square (при условии, что пользовательских преобразований не происходит).

Я бы посоветовал вам тщательно подумать, прежде чем идти по этому пути. Обычно такой акт означает, что вы несколько ломаете абстракцию - если вы знаете о shape как IShape, вы должны (обычно) быть в состоянии делать то, что вам нужно, только с участниками IShape. Если это не так, вы можете:

  • Сделайте IShape более сильным (дайте ему больше членов)
  • Измените свой код так, чтобы он принимал Square вместо IShape
  • В ролях, если это абсолютно необходимо
4 голосов
/ 08 ноября 2011

Проблема в том, что вы пытаетесь получить доступ к PrintMore() из ссылки IShape, ссылки IShape видят только объявленный ими метод Print().

Таким образом, ваш каст (Square) shape ничего не делает, потому что он сразу же сохраняет его в справочнике IShape. Сама ссылка должна быть Square либо путем приведения и сохранения ее в Square ссылке, либо путем приведения перед вызовом:

Square s = (Square) shape;
s.PrintMore();

Или

IShape s = shape;
((Square)s).PrintMore();

Или, если вы не уверены, является ли это Square или нет, используйте as приведение:

Square s = shape as Square;

// will cast if it is a Square, otherwise, returns null 
// this doesn't work for value types (int, struct, etc) 
if (s != null)
{
    s.PrintMore();
}
3 голосов
/ 08 ноября 2011

В строке IShape s = (Square)shape; вы сообщаете компилятору, что s является IShape, поэтому доступны только методы для IShape.

Если вы пользователь:

Square s = (Square)shape;
s.PrintMore()

Тогда это должно делать то, что вы хотите.

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

2 голосов
/ 08 ноября 2011
IShape s = (Square)shape; 
s.PrintMore();

С этим кодом s по-прежнему IShape, а не Square.Переменная сохраняет тип, который вы определили в его объявлении, независимо от того, что вы пытаетесь заполнить его.

Для работы код должен быть:

Square s = (Square)shape; 
s.PrintMore();
1 голос
/ 08 ноября 2011

Потому что при попытке s.PrintMore() "s" имеет тип IShape, поэтому он знает только о функциях интерфейса. Вам нужно сделать что-то вроде

Square s = (Square)shape;  
s.PrintMore();

или

((Square)shape).PrintMore(); // assuming you're positive its a Square type

Думайте об интерфейсе как обертке над вашим объектом, который предоставляет только те функции, которые определены в интерфейсе. Они все еще там, вы просто не можете получить к ним доступ без приведения к соответствующему объекту.

1 голос
/ 08 ноября 2011

Причина, по которой вы не можете получить доступ к методу PrintMore, заключается в том, что вы переназначаете приведенную к типу форму обратно в переменную, определенную как IShape. Чтобы иметь возможность использовать методы класса Square, необходимо сохранить его в переменной типа Square, например:

Square s = (Square)shape;
s.PrintMore(); 

или альтернативно:

((Square) shape).PrintMore();

Хотя, возможно, стоит хорошенько взглянуть на ваш код, приведение типов, например, обычно является хорошим предупреждением о том, что, возможно, он не идеален. Возможно, IShape должен иметь метод PrintMore, или, возможно, вы должны принимать только Square объекты в этой точке? По крайней мере, я бы посоветовал убедиться, что shape на самом деле имеет тип Square перед выполнением этого приведения типа.

Например:

Square s = shape as Square;

if (s != null)
    s.PrintMore(); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...