Почему этот Upcast не работает? - PullRequest
1 голос
/ 18 июня 2009

У меня есть 2 класса Test (базовый) и Program (дочерний). Теперь я сталкиваюсь с некоторой проблемой при унынии.

        Test t = new Program();// upcasting-works
        Program p = (Program)t;//Downcasting-works
        Program q = (Program)new Test();//Downcasting -throws exception.

Я хочу знать, почему это исключение? Может б очень простое, но как-то не получается. Это для этого нового объекта?

Спасибо.

Ответы [ 5 ]

7 голосов
/ 18 июня 2009

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

Program q = (Program)new Test();

Вы создаете экземпляр Test - экземпляр явно не соответствует Program, поскольку Test не является производным от Program. Во время выполнения компьютер обнаруживает, что это так, и выдает исключение.

С другой стороны, у вас есть:

 Test t = new Program();

Здесь вы создаете экземпляр Program - экземпляр соответствует Test, поскольку Program происходит от Test.

Наконец, и из строя, у вас есть:

Program p = (Program)t;

В этом случае t является ссылкой на Test, но базовый тип действительно Program - во время выполнения компьютер может определить, что это так, поэтому приведению разрешено работать. 1025 *

6 голосов
/ 18 июня 2009

Каждый квадрат - это прямоугольник, но не наоборот. Точно так же каждый экземпляр производного класса является допустимым экземпляром базового класса, но не наоборот. В вашем примере каждый Program является Test, но не все Test s Program s.

Примечание: чтобы уточнить, это не значит, что вы должны наследовать Square от Rectangle в ООП :) Это просто аналогия По иронии судьбы, аналогия является хорошо известной проблемой в ОО-дизайне.

1 голос
/ 18 июня 2009

Проблема: Test экземпляр не a Program. Это работает в первом случае, потому что экземпляр создается как Program (в первой строке).

Для приведений важен тип фактического объекта (а не только переменная).

0 голосов
/ 18 июня 2009

Мехрдад дал правильный ответ. Просто чтобы было понятнее:

Ваш Test равен , а не a Program - верно и обратное: Program is-a Test в вашем случае. Следовательно, то, что вы пытаетесь сделать, не является повышением, и это не разрешено.

0 голосов
/ 18 июня 2009

Думайте об этом так, вы можете привести Программу к Тесту, потому что Программа - Тест.

Вы не можете привести Тест к Программе, потому что Тест - это не Программа.

Это ВСЕГДА безопасно снижать, только безопасно, если вы уверены, что объект этого типа.

Необходимость перехода в исходное состояние часто является запахом кода, если вы обнаружите, что вам часто требуется преобразовать ваши объекты в объект, возможно, что-то не так с вашим дизайном.

Надеюсь, это поможет,

РЕДАКТИРОВАТЬ: Всегда ли безопасно снижать?

Акт понижения происходит по определению - по моему мнению, - когда вы знаете тип объекта, и вы понижаете его вниз по дереву наследования. например Кошка и собака оба наследуют от животных, дуб и береза ​​оба наследуют от дерева.

ВСЕГДА безопасно делать это

public void DoThingWithCat(Cat snuggles)
{
    snuggles.Meow();
    DoThingWithAnimal(snuggles); // this is always OK, because we know 
                                 // the type of snuggles, and we know 
                                 // snuggles is an animal
}

Это UpCast. Это небезопасно, также этот код является запахом кода, возможно, что-то не так с вашей иерархией объектов, если вам нужно это сделать.

public void DoSomethingElse(Animal anAnimal)
{
    DoThingWithCat(anAnimal);    // this is NOT always OK, because we
                                 // DO NOT know the type of anAnimal, 
                                 // and it may not be a Cat
}

Это также небезопасно, потому что это прямое литье, не обязательно литье вверх или вниз

public void DoSomethingDifferent(object anObject)
{
    DoThingWithAnimal(anObject); // this may or may not work, 
                                 // depending on the type passed in, 
                                 // this is a recipe for disaster, 
                                 // because may not be an Animal, 
                                 // it could be a Tree.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...