Nano Hash - криптовалюты, майнинг, программирование

Общий ввод функции Swift соответствует как классу, так и протоколу

Я пытаюсь, чтобы функция принимала общий ввод, который соответствует как классу, так и протоколу, чтобы обрабатывать значения, где некоторые принадлежат классу, а другие принадлежат делегату. Он отлично работает для отдельных типов, но не для массива типов (которые соответствуют как суперклассу, так и делегату). Вместо этого компилятор выдает ошибку. Метод экземпляра «printValues ​​(for:)» требует, чтобы «MeasurementClass» соответствовал «UnitDelegate».

Я добавил код ниже, который будет иметь гораздо больше смысла. Просто поместите его в Swift Playground. Если вы запустите его как есть, вы увидите, что он правильно печатает расстояние и шаги пользователя по отдельности. Если вы раскомментируете последние несколько строк, ту же функцию нельзя будет использовать с массивом.

Моя цель состоит в том, чтобы иметь возможность передавать массив типов, соответствующих UnitDelegate и MeasurementClass (он же псевдоним типа MeasurementObject), и обрабатывать значения. Я хочу массив, потому что мне понадобится куча разных классов, соответствующих MeasurementObject.

protocol UnitDelegate: class{
    var units: [String: String] { get }
}

class MeasurementClass{
    var imperial: Double!
    var metric: Double!
    
    convenience init(imperial: Double, metric: Double){
        self.init()
        self.imperial = imperial
        self.metric = metric
    }
}

typealias MeasurementObject = MeasurementClass & UnitDelegate


class Distance: MeasurementObject{
    var units = ["imperial": "miles", "metric":"kms"]
}

class Steps: MeasurementObject{
    var units = ["imperial": "steps", "metric":"steps"]
}

class User{
    func printValues<T: MeasurementObject>(for type: T) {
        print("\(type.imperial!) \(type.units["imperial"]!) = \(type.metric!) \(type.units["metric"]!)")
    }
}

//This is what I'm trying to achieve in the for loop below
let distance = Distance(imperial: 30, metric: 48.28)
let steps    = Steps(imperial: 30, metric: 30)
let user     = User()
user.printValues(for: distance)
user.printValues(for: steps)


//let types = [distance, steps]
//
//for type in types{
//    user.printValues(for: type)
//}

  • Это не то, как работает дженерик. Вы не можете смешивать общие типы в коллекции. Общий тип может быть любым типом, но только одним за раз. 21.11.2020
  • ` вар империал: Двойной! var metric: Double!` Я гарантирую вам, что эти два значения не будут синхронизированы. Храните только один источник правды, т.е. стандартное значение метрики, а британское измерение сделать вычисляемым свойством, которое получает правильное преобразование на лету. Таким образом, он никогда не может выйти из синхронизации 21.11.2020
  • @Alexander-ReinstateMonica Я подумал об этом и решил, что это лучшее. Я храню кучу типов здоровья на сервере, и, имея имперские и метрические значения, я могу просто получить правильное значение. Если бы у меня были только имперские единицы, мне пришлось бы каким-то образом включить тип данных, извлекаемых для выполнения преобразования. Имея все записи о работоспособности с одинаковыми значениями на сервере, на стороне собственного приложения я могу использовать один класс для декодирования каждого типа. 21.11.2020
  • @RichardWitherspoon Я предлагаю вам выделить одно значение как единственное, которое стоит хранить. Взгляните на API единиц измерения и измерений, встроенный Apple в Foundation. Судя по тому немногому, что я видел в вашем коде/проблеме, он точно соответствует тому, что вы пытаетесь сделать. Если нет, вы могли бы хотя бы сослаться на него, например, на их базовые единицы: developer.apple.com/ документация/основа/размер 21.11.2020
  • Я понятия не имел об этом, это будет идеально! Большое спасибо. 22.11.2020

Ответы:


1

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

struct AMeasurement {
    let imperial: Double
    let metric: Double
    let kind: Kind
    enum Kind { case distance, steps }
    var units: [String: String] {
        switch kind {
        case .distance: return ["imperial": "miles", "metric":"kms"]
        case .steps: return ["imperial": "steps", "metric":"steps"]
        }
    }
}

extension AMeasurement {
    func printValues() {
        print("\(imperial) \(units["imperial"]!) = \(metric) \(units["metric"]!)")
    }
}

let distance = AMeasurement(imperial: 30, metric: 48.28, kind: .distance)
let steps = AMeasurement(imperial: 30, metric: 30, kind: .steps)
let types = [distance, steps]

for type in types {
    type.printValues()
}

30,0 миль = 48,28 км
30,0 шагов = 30,0 шагов

20.11.2020
  • Это гораздо более простой подход к решению моей проблемы. Кажется, я слишком усложнил ответ. Спасибо за помощь! 22.11.2020
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..