Как я могу принять один из двух типов в качестве аргумента функции?

Я хотел бы написать функцию, которая принимает только Int или Double и возвращает на их основе разные значения. Реальный вариант использования представляет собой SwiftUI struct: View с несколько более сложным init(). Если возможно, я бы хотел избежать дублирования с другим типом ввода. Как это может быть сделано?

В идеале мне бы хотелось решение, которое выглядит так:

struct MyStruct<T>: View where T is (Int | Double) {  // Specifying type here is the problematic part
var value: T
var description: String

init(_ value: T) {
   self.value = value
   switch value {
      case is Int:
         description = "Integer"
      case is Double:
         description = "Double"
   }
}

var body: some View {
   Text(description)
}

Связано: stackoverflow.com/q/53004623/1187415

Martin R 20.04.2024 12:53

Только Int или Double? Вы уверены, что не можете обобщить это на общий протокол, такой как SignedNumeric?

Sweeper 20.04.2024 13:51
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Есть как минимум два варианта:

  1. Пользовательский фиктивный протокол, который Int и Double принимается в расширении.

    protocol IntOrDouble {}
    extension Int : IntOrDouble {}
    extension Double : IntOrDouble {}
    
    struct MyStruct<T>: View where T : IntOrDouble {
        var value: T
        let description: String
    
        init(_ value: T) {
           self.value = value
            description = value is Int ? "Integer" : "Double"
        }
    
        var body: some View {
            Text(description)
        }
    }
    
  2. Перечисление со связанными значениями

    enum IntOrDouble {
        case integer(Int)
        case double(Double)
    }
    
    struct MyStruct: View, CustomStringConvertible {
        var value: IntOrDouble
    
        var body: some View {
            Text(description)
        }
    
        var description : String {
            switch value {
                case .integer(let intValue):
                    return "Integer \(intValue)"
                case .double(let doubleValue):
                    return "Double \(doubleValue)"
            }
        }
    }
    
value is Int ? "Integer" : "Double" это подвержено ошибкам, потому что вы можете добавить новое соответствие к IntOrDouble (что маловероятно, учитывая имя, но случаются и более странные вещи), что всегда будет неправильно соответствовать регистру "double".
Alexander 22.04.2024 15:28

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

import SwiftUI

protocol MyType {
    var typeDescription: String { get }
}

extension Int: MyType {
    var typeDescription: String {
        return "Integer"
    }
}

extension Double: MyType {
    var typeDescription: String {
        return "Double"
    }
}

struct MyStruct<T: MyType>: View {
    var value: T
    
    var body: some View {
        Text(value.typeDescription)
    }
}

#Preview {
    MyStruct(value: 2) // Integer
    //MyStruct(value: 2.3) // Double
}

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