У меня есть валидатор абстрактного базового класса с методом, который принимает общий тип в качестве параметра. Я буду передавать параметр универсального типа базовому классу из подкласса, наследующего базовый класс.
Базовый класс:
abstract class BaseValidator {
bool isValid<T>(T obj);
}
Детский класс:
class IPv4Validator extends BaseValidator{
final IPV4_REGEX = "^((25[0-5]|(2[0-4]|1d|[1-9]|)d).?\b){4}\$";
@override
bool isValid<String>(String obj) {
bool hasMatch = RegExp(IPV4_REGEX).hasMatch(obj);
return hasMatch;
}
}
Здесь hasMatch
принимает строку, не допускающую значение NULL. Когда я напрямую передаю какую-то строку, hasMatch не выдает ошибку.
Но когда я пытаюсь передать общее значение в параметре метода, он показывает ошибку.
Тип аргумента «Строка» не может быть назначен типу параметра 'Нить'.
Я не мог понять, почему общий тип не принимается, хотя его тип времени компиляции.
Это не решит проблему, так как у меня нет проблем со строкой IPV4_REGEX
. Проблема в obj
String, который является универсальным типом.
isValid<String>(String obj)
определяет общий метод с именем isValid
, параметр типа которого имеет имя String
. Он идентичен isValid<T>(T obj)
, но с более вводящим в заблуждение именем параметра типа (и именно поэтому вы получаете сбивающее с толку сообщение об ошибке о том, что String
нельзя присвоить String
). Он не определяет метод с именем isValid
, который принимает только String
аргументы.
Привет @jamesdlin. Спасибо за Ваш ответ. Ваш комментарий натолкнул меня на мысль. Но немного запутанно. Ответ Касымебека решил мой. Но мне было интересно, почему параметр типа работает в классах, а не для методов. Насколько я знаю, оба параметра типа являются только типом компиляции. Тогда почему существует разница между параметрами типа в классе и методе. Я был бы полезен, если бы вы могли предоставить расширенный ответ о разнице между моей реализацией и принятым ответом.
@GowthamKK Я не понимаю, что ты имеешь в виду. Вы можете иметь как общие классы, так и методы. Как я уже говорил, isValid<String>(String obj)
не делает то, что вам нужно, потому что объявляет универсальный метод, а не специализацию существующего универсального метода. Это ничем не отличается от объявления универсального класса с помощью class SomeGeneric<String>
: в этом случае String
— это не класс String
, а произвольное имя параметра универсального типа.
Следующий код решает эту конкретную проблему. Но он может отличаться от того, что вы намеревались реализовать. С другой стороны, код будет чище, если вы создадите новый конкретный класс для разных типов данных.
abstract class BaseValidator<T> {
bool isValid(T obj);
}
class IPv4Validator extends BaseValidator<String>{
final IPV4_REGEX = "^((25[0-5]|(2[0-4]|1d|[1-9]|)d).?\b){4}\$";
@override
bool isValid(String obj) {
bool hasMatch = RegExp(IPV4_REGEX).hasMatch(obj);
return hasMatch;
}
}
Объяснение.
В строке class IPv4Validator extends BaseValidator<String>
мы не объявляем новый класс BaseValidator
, он уже объявлен как BaseValidator<T>
. Здесь мы наследуем специализацию существующего универсального класса BaseValidator
. Находясь в строке bool isValid<String>(String obj)
, мы объявляем новую функцию, поэтому компилятор понимает это так, как если бы мы объявляли новую универсальную функцию с типом параметра с именем String
. Итак, здесь bool isValid<String>(String obj)
эквивалентно bool isValid<T>(T obj)
, только вместо имени T
мы использовали имя String
, которое не является объектом String
.
Спасибо за Ваш ответ. Это работает. Но я думал о другом. Почему параметр типа работает в классах, а не в методах?
@GowthamKK Я отредактировал свой ответ, чтобы добавить объяснение. Это то же самое, что Джеймсдлин написал в комментариях.
другое исправление, которое вы можете сделать, это использовать ключевое слово covariant
, чтобы реализовать это, попробуйте следующее:
abstract class BaseValidator<T> {
bool isValid(T obj);
}
class IPv4Validator extends BaseValidator {
final IPV4_REGEX = "^((25[0-5]|(2[0-4]|1d|[1-9]|)d).?\b){4}\$";
@override
bool isValid(covariant String obj) {
bool hasMatch = RegExp(IPV4_REGEX).hasMatch(obj);
return hasMatch;
}
}
попробуйте указать тип вашего регулярного выражения:
final String IPV4_REGEX = "...";