Метод дженериков Dart не распознает тип

У меня есть валидатор абстрактного базового класса с методом, который принимает общий тип в качестве параметра. Я буду передавать параметр универсального типа базовому классу из подкласса, наследующего базовый класс.

Базовый класс:

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 не выдает ошибку. Но когда я пытаюсь передать общее значение в параметре метода, он показывает ошибку.

Тип аргумента «Строка» не может быть назначен типу параметра 'Нить'.

Я не мог понять, почему общий тип не принимается, хотя его тип времени компиляции.

попробуйте указать тип вашего регулярного выражения: final String IPV4_REGEX = "...";

john 19.11.2022 07:44

Это не решит проблему, так как у меня нет проблем со строкой IPV4_REGEX. Проблема в obj String, который является универсальным типом.

Gowtham K K 19.11.2022 07:50
isValid<String>(String obj) определяет общий метод с именем isValid, параметр типа которого имеет имя String. Он идентичен isValid<T>(T obj), но с более вводящим в заблуждение именем параметра типа (и именно поэтому вы получаете сбивающее с толку сообщение об ошибке о том, что String нельзя присвоить String). Он не определяет метод с именем isValid, который принимает только String аргументы.
jamesdlin 19.11.2022 08:05

Привет @jamesdlin. Спасибо за Ваш ответ. Ваш комментарий натолкнул меня на мысль. Но немного запутанно. Ответ Касымебека решил мой. Но мне было интересно, почему параметр типа работает в классах, а не для методов. Насколько я знаю, оба параметра типа являются только типом компиляции. Тогда почему существует разница между параметрами типа в классе и методе. Я был бы полезен, если бы вы могли предоставить расширенный ответ о разнице между моей реализацией и принятым ответом.

Gowtham K K 19.11.2022 19:24

@GowthamKK Я не понимаю, что ты имеешь в виду. Вы можете иметь как общие классы, так и методы. Как я уже говорил, isValid<String>(String obj) не делает то, что вам нужно, потому что объявляет универсальный метод, а не специализацию существующего универсального метода. Это ничем не отличается от объявления универсального класса с помощью class SomeGeneric<String>: в этом случае String — это не класс String, а произвольное имя параметра универсального типа.

jamesdlin 19.11.2022 20:00
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
0
5
92
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

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.

Спасибо за Ваш ответ. Это работает. Но я думал о другом. Почему параметр типа работает в классах, а не в методах?

Gowtham K K 19.11.2022 19:17

@GowthamKK Я отредактировал свой ответ, чтобы добавить объяснение. Это то же самое, что Джеймсдлин написал в комментариях.

Kasymbek R. Tashbaev 20.11.2022 07:32

другое исправление, которое вы можете сделать, это использовать ключевое слово 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;
  }
}

Другие вопросы по теме