2016-08-05 3 views
3

Я пишу класс Scala, который расширяет класс Java. Я должен расширить этот абстрактный Java-класс, потому что он содержит некоторые конвертеры, и мне нужно написать собственный конвертер, который я могу подключить к своей структуре. Таким образом, подпись метода ниже навязывается мне: она генерируется автоматически Eclipse, когда я говорю, что мой класс расширяет их абстрактный класс. Если я попытаюсь изменить подпись метода, класс не скомпилируется, потому что «он не реализует абстрактный метод от родителя».абстрактный тип T не отмечен, так как он устранен стиранием

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

Мне нужно сделать что-то очень просто: обработать «None» как null и вернуть что-нибудь еще, как есть. Но я считаю, что я не могу сделать это безопасным способом. Если я напишу код, как показано ниже, я получаю предупреждение о том, что «абстрактный тип T не отмечен, поскольку он устраняется стиранием». Как я могу это устранить?

Я также задаюсь вопросом, как мой код будет выглядеть после стирания, если применить к нему, т. Е. Что будет выглядеть второе условие «если».

Интуитивно я понимаю, что я не могу гарантировать возвращение T, когда входной сигнал Any - вот почему компилятор недоволен. На практике это будет работать, потому что мы просто читаем строки и возвращаем строки, но подпись метода навязывается мне декларацией наследования.

def execute[T](value: Any): T = { 
    if (value == null || value == "None") null.asInstanceOf[T] 
    // Warning: abstract type T is unchecked since it is eliminated by erasure 
    else if (value.isInstanceOf[T]) value.asInstanceOf[T] 
    //   warning here:^
    else null.asInstanceOf[T] 
    } 

Как реализовать этот метод?

+1

Возможно, это может помочь: [http://stackoverflow.com/questions/1094173](http://stackoverflow.com/questions/1094173). – paulotorrens

+0

Поскольку стирание превращает второй оператор «if» в «isInstanceOf [Object]», что всегда верно, на самом деле это гарантировано, что он не выполняет то, что планировал программист. Я шокирован, что это предупреждение, а не ошибка. Я понимаю, что эта проблема не может быть решена безопасным типом, потому что вход - это Any, а выход - T. То, что я понимаю из решения Alexey, состоит в том, что, как только вы начинаете делать такие вещи, вы в основном говорите компилятору «доверяете» я, во время выполнения, это будет зависеть от T ", а« гарантия безопасности типа компилятора »станет« Я вижу, что программист пообещал T ». – radumanolescu

ответ

2

Ваше решение Java не содержит теста value instanceof T, поэтому вам не нужно isInstanceOf[T] в решении Scala. И вы должны удалить его, потому что чек ничего не делает: он стирает до isInstanceOf[Object], что всегда верно, поэтому последняя ветка else никогда не берется. Оставшаяся разница в том, что в Java вы сравниваете String.valueOf(value) с "None", а не value.Таким образом, эквивалент решения Java является

def execute[T](value: Any): T = { 
    (if (value == null || String.valueOf(value) == "None") null else value).asInstanceOf[T] 
} 

условие может быть упрощено до value == null || value.toString == "None", по определению String.valueOf.

IMO, компилятор должен дать предупреждение для asInstanceOf[T], а не только для isInstanceOf[T]; это случай, когда Java на самом деле безопаснее, чем Scala, потому что 1) он дает предупреждение для приведения; 2) проверка instanceof будет ошибкой, а не предупреждением.

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

1

В конце концов, я могу сделать один из двух вещей:

  1. реализовать в Java:

    @SuppressWarnings ("непроверенный") @Override выполнения (значение Object) общественное T { if (value == null || "None" .equals (String.valueOf (value))) return null; значение возврата (T); }

  2. реализовать в Scala и добавить @unchecked

    четкости выполнения [T] (значение: есть): T = { , если (значение == NULL || значение == "None") нуль. asInstanceOf [Т] иначе, если (value.isInstanceOf [Т @unchecked]) value.asInstanceOf [Т] еще null.asInstanceOf [Т]}

Я до сих пор интересно, что осталось от второй, если после стирания.

Спасибо Алек за предложение!

+0

Это делает то, что вы хотите? Все, что вы делаете, это подавление предупреждения ... – Alec

+0

Erasure все равно получит вас. Если вы не можете добавить 'ClassTag' или' Manifest', вы можете быть SOL и должны использовать реализацию Java. – JRomero

+0

Если я посмотрю код Java, я уверен, что он делает то, что я хочу, потому что понимаю, что он делает. Практически ни одна из реализаций не зависит от T. Отбрасывание в конце можно игнорировать, и я все еще получаю то, что хочу. В Scala я не понимаю, что делает второй оператор if после стирания. Я должен буду испытать. – radumanolescu

Смежные вопросы