ООП C # Вопрос: превращение фрукта в грушу - PullRequest
4 голосов
/ 10 июня 2010

Учитывая, что у меня есть экземпляр Fruit с некоторыми установленными свойствами, и я хочу получить эти свойства в новом экземпляре Pear (потому что этот конкретный Fruit имеет свойства груши), какой лучший способ добиться этого эффект?

Например, то, что мы не можем сделать, это просто бросить фрукт в грушу, потому что не все фрукты - груши:

public static class PearGenerator {
    public static Pear CreatePear () {

        // Make a new generic fruit.
        Fruit genericFruit = new Fruit();

        // Upcast it to a pear. (Throws exception: Can't cast a Fruit to a Pear.)
        Pear pear = (Pear)genericFruit;

        // Return freshly grown pear.
        return ( pear );
    }
}

public class Fruit {
    // some code
}

public class Pear : Fruit {

    public void PutInPie () {
        // some code
    }

}

Спасибо!

Обновление:

Я не контролирую код "new Fruit ()". Моя отправная точка в том, что у меня есть Fruit для работы. Мне нужно как-то перенести этот фрукт в новую грушу. Может быть, скопировать все свойства по одному?

Ответы [ 11 ]

15 голосов
/ 10 июня 2010

Потому что фрукт, который вы создали , не груша!


Изменить: Если у вас уже есть Fruit и вам нужно создать Pear из него, тогда да, у вас нет выбора, кроме как скопировать все свойства в новый объект Pear. В идеале это должно быть сделано в конструкторе Pear, который вы создаете специально для этой цели.

13 голосов
/ 10 июня 2010

Это не груша.Попробуйте заменить свою строку

Fruit genericFruit = new Fruit();

на:

Fruit genericFruit = new Pear();
5 голосов
/ 10 июня 2010

Сбой downcast , потому что созданный экземпляр - Fruit, чтобы сделать его Pear, измените код на

    // Make a Pear - it looks like a fruit, tastes like a fruit,
    // and quacks like a fruit. It must be a fruit.
    Fruit genericFruit = new Pear();

    // Downcast it to a pear. 
    Pear pear = (Pear)genericFruit;

Приведение вниз приводит к фактическому типу, а не к объявленному типу - но вы не знаете, что это за фактический тип (если вы не тестируете с использованием is / as). Вот почему это немного опасно, и большинство людей стараются избегать удручения, где это возможно.

РЕДАКТИРОВАТЬ: Чтобы превратить фрукт в грушу, вы можете сами создать новую Грушу и инициализировать ее как можно лучше. Можно скопировать некоторые свойства, общие для всех фруктов, от фруктов до груши. Но это также может быть похоже на попытку поставить квадратный колышек в круглое отверстие, смешивая ваши метафоры и заканчивая фруктовым пюре.

4 голосов
/ 10 июня 2010

Груша - это фрукт.

Фрукт - это не обязательно груша.

3 голосов
/ 10 июня 2010

Если вы не отвечаете за Fruit, но являетесь автором Pear, то, возможно, вам поможет другой дизайн:

Может быть, лучше изменить класс Pear на большееFruitWrapper класс.Этот класс будет содержать ссылку на Fruit вместо того, чтобы быть более конкретным видом Fruit.Он может иметь свою собственную функциональность (причина, по которой вы не хотите использовать Fruit в первую очередь), и передавать функциональность фруктового типа к Fruit, который находится внутри.Если ему нужно работать с библиотечным кодом, который ожидает Fruit, просто передайте тот, который он держит, на ...

2 голосов
/ 10 июня 2010

Когда вы ведете кастинг, вы на самом деле не изменяете какие-либо данные, просто «лейбл», если хотите.Если у вас есть Груша, которая была брошена в Фрукт, то она может быть снова превращена в Грушу, но если она никогда не была Грушей, то кастинг не превратит ее в Грушу.

2 голосов
/ 10 июня 2010

Если Груша определила множество новых вещей .. и вы создали Fruit.

Если вы повышаете рейтинг Fruit to Pear, на что следует установить все дополнительные элементы в Pear?Следовательно, почему это не разрешено!

1 голос
/ 10 июня 2010

Абсолютно необходимо наследовать?

... Я думаю, что пример "Груша -> фрукты" делает это жестким ... это пример верно?

А как насчет создания вашего класса Pear, например:

public class Pear { 

    public Fruit {get; set;}

    public void Pear(add pear properties, Fruit fruit)
    {
         // assign pear properties
         Fruit = fruit;
    }

    public void PutInPie () { 
        // some code 
    } 

}

Возможно, это не идеал, но это идея.

Удачи,

Patrick

0 голосов
/ 10 июня 2010

Этот пример напоминает мне пример из этой статьи . Взгляните там на интересное обсуждение наследования против композиции. Подумайте о проблеме хрупкого базового класса . Чтобы отобразить один объект на другой, вы можете использовать AutoMapper .

0 голосов
/ 10 июня 2010

Вы можете создать новый конструктор для Pear, который принимает экземпляр Fruit.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...