Способ бросить базовый тип к производному типу

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

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

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

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

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

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

45
задан Naser Asadi 3 June 2014 в 07:28
поделиться

11 ответов

Не обоснованно, на "управляемых" языках. Это downcasting, и там не нормально вниз способ обработать его, по точно причине, которую Вы описали (подклассы обеспечивают больше, чем базовые классы - куда это "больше" прибывает из?). Если Вы действительно хотите подобное поведение для конкретной иерархии, Вы могли бы использовать конструкторов для производных типов, которые возьмут базовый тип в качестве прототипа.

можно было создать что-то с отражением, которое обработало простые случаи (более определенные типы, которые не имеют никакого дополнительного состояния). В целом, просто модернизация для предотвращения проблемы.

Редактирование: Ой, не может записать операторы преобразования между основой/производными типами. Причуда попытки Microsoft "защитить Вас" от себя. А-ч хорошо, по крайней мере, они не где рядом настолько же плохо как Sun.

31
ответ дан lomaxx 26 November 2019 в 21:11
поделиться

Это не может работать. Пойдите посмотреть на страницу справки, связанную ошибкой компиляции.

лучшее решение состоит в том, чтобы использовать методы фабрики здесь.

0
ответ дан hichris123 26 November 2019 в 21:11
поделиться

Это не возможно потому что, как Вы собираетесь получить "дополнительное", которое имеет производный класс. Как компилятор знал бы о значении derivedClass1 и не derivedClass2 при инстанцировании его?

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

0
ответ дан Laplie Anderson 26 November 2019 в 21:11
поделиться

Это называют downcasting, и предложение Seldaek для использования "безопасной" версии является звуковым.

Вот довольно достойное описание с примерами кода .

0
ответ дан Ben Hoffstein 26 November 2019 в 21:11
поделиться

Да - это - запах кода, и в значительной степени закрепляет то, что Ваша цепочка наследования повреждается.

Мой предположение (от ограниченного образца) - то, что Вы сделали бы, чтобы DerivedClass воздействовал на экземпляр SomeBaseClass - так, чтобы "DerivedClass имел , SomeBaseClass", а не "DerivedClass SomeBaseClass". Это известно как "состав пользы по наследованию".

1
ответ дан Mark Brackett 26 November 2019 в 21:11
поделиться

Downcasting имеет смысл, если у Вас есть Объект производного класса, но на это ссылается ссылка типа базового класса, и по некоторым причинам Вы хотите, чтобы он назад был сослан ссылкой типа производного класса. Другими словами, Вы можете удрученный для инвертирования эффекта предыдущего upcasting. Но у Вас не может быть объекта базового класса, на который ссылается ссылка типа производного класса.

9
ответ дан Maciej Hehl 26 November 2019 в 21:11
поделиться

Нет, это не возможно. На управляемом языке как C# это просто не будет работать. Время выполнения не позволит его, даже если компилятор пропустит его.

Вы сказали себя, что это кажется глупым:

SomeBaseClass class = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)class; 

Так спрашивают себя, class на самом деле экземпляр SomeDerivedClass? Нет, таким образом, преобразование не имеет никакого смысла. Если необходимо преобразовать SomeBaseClass в SomeDerivedClass, то необходимо обеспечить некоторое преобразование, или конструктор или метод преобразования.

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

5
ответ дан Derek Park 26 November 2019 в 21:11
поделиться

Попробуйте состав вместо наследования!

Это кажется мне как, Вы были бы более обеспеченной передачей экземпляра SomeBaseClass к SomeDerivedClass (который больше не будет получать базовый класс и должен быть переименован как таковой)

public class BooleanHolder{       
    public bool BooleanEvaluator {get;set;}
}

public class DatabaseInserter{
    BooleanHolder holder;

    public DatabaseInserter(BooleanHolder holder){
        this.holder = holder;
    }

    public void Insert(SqlConnection connection) {
          ...random connection stuff
          cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar;
          ...
    }
}

public static void Main(object[] args) {
    BooleanHolder h = new BooleanHolder();
    DatabaseInserter derClass = new DatabaseInserter(h);
    derClass.Insert(new sqlConnection);
}

Выезд http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html (страница 3):

Повторное использование кода через состав Состав обеспечивает альтернативный путь к Apple к реализации Фруктов повторного использования кожицы (). Вместо того, чтобы расширить Фрукты, Apple может содержать ссылку на Фруктовый экземпляр и определить его собственную кожицу () метод, который просто вызывает кожицу () на Фруктах.

18
ответ дан Rob Fonseca-Ensor 26 November 2019 в 21:11
поделиться

Как другие отметили, кастинг, Вы предлагаете, не действительно возможно. Это, возможно, был бы случай, где Шаблон "декоратор" (Возглавляют Первое извлечение) может быть представлен?

1
ответ дан Boris Callens 26 November 2019 в 21:11
поделиться

Задумывались ли вы об интерфейсе, который в настоящее время будет реализован в вашем базовом и производном классах? Я не знаю, почему вы применяете этот способ, но он может сработать.

1
ответ дан 26 November 2019 в 21:11
поделиться

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

SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass
if(class is SomeDerivedClass)
    ;

- редактирование я задал этот вопрос давно

,
0
ответ дан 26 November 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: