Протокол наследования и структуры в быстром - PullRequest
1 голос
/ 05 апреля 2019

Я хочу создать протокол Validatable, который имеет два свойства: validator и isAbleToProceed логическое значение:

protocol Validatable {
    var validator: Validator { get set }
    var isAbleToProceed: Bool { get set }
}

Я хочу определить различные типы Validators (валидатор даты рождения, валидатор электронной почты и т. Д.). Для этого я создал фабрику:

protocol Validator {}

struct ValidatorFactory {
    internal static let sharedInstance = ValidatorFactory()

    func dateOfBirthValidator(minimumAge: Int, maximumAge: Int) -> DateOfBirthValidator {
        return DateOfBirthValidator(minimumAge: minimumAge, maximumAge: maximumAge)
    }

    func driversLicenseValidator(minLicenseDuration: Int) -> DriversLicenseValidator {
        return DriversLicenseValidator(minLicenseDuration: minLicenseDuration)
    }
}

и это реализация DateOfBirthValidator:

struct DateOfBirthValidator: Validator {
    let minimumAge: Int
    let maximumAge: Int

    func isDateOfBirthValid(date: Date) -> Bool {
        if let age = Calendar.current.dateComponents([.year], from: date, to: Date()).year {
            return (minimumAge ... maximumAge).contains(age)
        } else {
            return false
        }
    }
}

Тогда у меня будет класс ViewController, реализующий протокол Validatable:

class ViewController: Validatable {

    // MARK: Internal Properties

    internal var validator: DriversLicenseValidator
    internal var isAbleToProceed: Bool = false

}

Но компилятор сообщит, что ViewController не соответствует Validatable (не имеет валидатора)

Это можно решить, если я сделаю Validator суперклассом, и все структуры валидаторов превратятся в классы и наследуются от него. Но есть ли способ заставить его работать со структурами и протоколами?

1 Ответ

2 голосов
/ 05 апреля 2019

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

есть пара ошибок Swift

Теперь в вашем случае у вас есть свойство get / set (по крайней мере, так, как оно объявлено в протоколе; вы сделали это let в своей реализации).

Из-за принципа подмены Лискова я должен быть в состоянии сказать:

var someValidatable = ViewController() as Validatable
someValidateable.validator = SocialSecurityValidator()

Если бы вы смогли сделать то, что вы хотите, это не получилось бы по двум причинам:

  1. validator имеет более ограниченный доступ и составляет let вместо var
  2. A SocialSecurityValidator нельзя назначить на validator, поскольку он имеет тип DriversLicenseValidator
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...