Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何在Swift中使函数的返回类型通用 简介_Arrays_Swift_Class_Generic Programming - Fatal编程技术网

Arrays 如何在Swift中使函数的返回类型通用 简介

Arrays 如何在Swift中使函数的返回类型通用 简介,arrays,swift,class,generic-programming,Arrays,Swift,Class,Generic Programming,在我的应用程序中,我有一个名为“ElementData”的超类和几个继承自它的子类 每个子类都有自己的validateModel()方法,该方法返回 不同的类型,取决于类-始终在数组中 换句话说:该方法在每个子类中返回不同的类型 例子 A类:func validateModel()->[String] B类:func validateModel()->[Int] C类:func validateModel()->[MyCustomEnum] 如您所见,只有返回值彼此不同 EDIT:validat

在我的应用程序中,我有一个名为“ElementData”的超类和几个继承自它的子类

每个子类都有自己的validateModel()方法,该方法返回 不同的类型,取决于类-始终在数组中

换句话说:该方法在每个子类中返回不同的类型

例子 A类:
func validateModel()->[String]

B类:
func validateModel()->[Int]

C类:
func validateModel()->[MyCustomEnum]

如您所见,只有返回值彼此不同

EDIT:validateModel()方法的示例:

func validateModel() -> [DefaultElementFields]{ // DefaultElementFields is an enum with the different view types of my collection view

        var checkResult: [DefaultElementFields] = []

        if name == "" {
            checkResult.append(.Name)
        }

        if Int(rewardedPoints) == nil {
            checkResult.append(.Points)
        }

        if description == "" {
            checkResult.append(.Description)
        }

        if selectedImage == nil {
            checkResult.append(.Image)
        }

        return checkResult
    }
func validateModel() -> [Int] { // returns the index of the text field which is wrong
        var checkResult: [Int] = []

        let filledValues = codes.filter {
            $0 != ""
        }

        if filledValues.count == 0 { // if no values have been entered, all fields should be marked red.
            checkResult.append(-1)
            return checkResult
        }


        for (i, code) in codes.enumerated() {
            if code != "" && (code.count < 3 || code.count > 10 || code.rangeOfCharacter(from: NSCharacterSet.alphanumerics.inverted) != nil){ // code must have more than 3 and less than 11 characters. No symbols are allowed.
                checkResult.append(i)
            }
        }



        return checkResult
    }
class ElementData {

    func validateModel<T>() -> [T] {
        return [1] as! [T] // just a test return
    }

}
dataObject.validateModel() // dataObject inherits from ElementData -> has access to validateModel()
A类:

func validateModel() -> [DefaultElementFields]{ // DefaultElementFields is an enum with the different view types of my collection view

        var checkResult: [DefaultElementFields] = []

        if name == "" {
            checkResult.append(.Name)
        }

        if Int(rewardedPoints) == nil {
            checkResult.append(.Points)
        }

        if description == "" {
            checkResult.append(.Description)
        }

        if selectedImage == nil {
            checkResult.append(.Image)
        }

        return checkResult
    }
func validateModel() -> [Int] { // returns the index of the text field which is wrong
        var checkResult: [Int] = []

        let filledValues = codes.filter {
            $0 != ""
        }

        if filledValues.count == 0 { // if no values have been entered, all fields should be marked red.
            checkResult.append(-1)
            return checkResult
        }


        for (i, code) in codes.enumerated() {
            if code != "" && (code.count < 3 || code.count > 10 || code.rangeOfCharacter(from: NSCharacterSet.alphanumerics.inverted) != nil){ // code must have more than 3 and less than 11 characters. No symbols are allowed.
                checkResult.append(i)
            }
        }



        return checkResult
    }
class ElementData {

    func validateModel<T>() -> [T] {
        return [1] as! [T] // just a test return
    }

}
dataObject.validateModel() // dataObject inherits from ElementData -> has access to validateModel()
B类:

func validateModel() -> [DefaultElementFields]{ // DefaultElementFields is an enum with the different view types of my collection view

        var checkResult: [DefaultElementFields] = []

        if name == "" {
            checkResult.append(.Name)
        }

        if Int(rewardedPoints) == nil {
            checkResult.append(.Points)
        }

        if description == "" {
            checkResult.append(.Description)
        }

        if selectedImage == nil {
            checkResult.append(.Image)
        }

        return checkResult
    }
func validateModel() -> [Int] { // returns the index of the text field which is wrong
        var checkResult: [Int] = []

        let filledValues = codes.filter {
            $0 != ""
        }

        if filledValues.count == 0 { // if no values have been entered, all fields should be marked red.
            checkResult.append(-1)
            return checkResult
        }


        for (i, code) in codes.enumerated() {
            if code != "" && (code.count < 3 || code.count > 10 || code.rangeOfCharacter(from: NSCharacterSet.alphanumerics.inverted) != nil){ // code must have more than 3 and less than 11 characters. No symbols are allowed.
                checkResult.append(i)
            }
        }



        return checkResult
    }
class ElementData {

    func validateModel<T>() -> [T] {
        return [1] as! [T] // just a test return
    }

}
dataObject.validateModel() // dataObject inherits from ElementData -> has access to validateModel()
不幸的是,它不起作用,我得到以下错误:

“无法推断泛型参数'T'”

总结:
  • 我有一个超类“ElementData”和几个子类(继承的类)
  • 每个子类都有一个验证模型的方法validateModel()
  • 只有子类中validateModel()方法的返回类型不同——因此我想将该方法放在父类(ElementData)中,然后在子类上覆盖它
是否可能,如果可能,如何实现?

任何帮助都将不胜感激。

这是不可能的

什么是泛型 假设您有此函数:

func identity(_ value: Any) -> Any {
    return value
}
它实际上不起作用:

let i = 5
assert(identity(i) == i) // ❌ binary operator '==' cannot be applied to operands of type 'Any' and 'Int'
任何
都会导致类型信息丢失。尽管我们看到参数的类型和返回值总是相同的,但我们还没有向类型系统表达这一点。这是泛型类型参数的完美用例。它允许我们表达参数类型和返回值之间的关系

func identity<T>(_ value: T) -> T {
    return value
}

let i = 5
assert(identity(i) == i) // ✅
func标识(u值:T)->T{
返回值
}
设i=5
断言(标识(i)=i)//✅
什么是非专利药 回顾您的问题,您会发现这里没有要表达的类型关系

  • ClassA.validateModel()
    始终返回
    [String]
  • ClassB.validateModel()
    始终返回
    [Int]
  • ClassC.validateModel()
    始终返回
    [MyCustomEnum]
那不是一般的

它是如何工作的? 假设您有一个类型为
ElementData
的对象。该对象可以是
ElementData
,或
ClassA
,或
ClassB
,或
ClassC
的实例。假设这四种类型都是可能的,并且假设存在一些混合物来做您想要做的事情,那么这段代码将如何工作

let elementData = someElementData()
let validatedModel = elementData.validateModel() // A possible solution is a protocol with associated types. You have to specify the return type as 
typealias
in each subclass.

protocol Validatable {
    associatedtype ReturnType
    func validateModel() -> [ReturnType]
}

class ElementData {}

class SubClassA : ElementData, Validatable {
    typealias ReturnType = Int

    func validateModel() -> [Int] { return [12] }

}

class SubClassB : ElementData, Validatable {
    typealias ReturnType = String

    func validateModel() -> [String] { return ["Foo"] }
}
let elementData=someElementData()

让validatedModel=elementData.validateModel()//一个可能的解决方案是使用关联类型的协议。必须在每个子类中将返回类型指定为
typealias

现在编译器知道所有子类的不同返回类型


请向我们展示至少两种验证方法的实现。有两种可能性。使用协议而不是超类,或者使整个类成为泛型。要推断泛型类型,必须执行类似于
let array:[Int]=dataObject.validateModel()的操作
使用返回值推断类型。@Sulthan但为了访问该方法并知道它返回什么,我仍然必须向下转换每个对象,对吗?顺便说一句:请参阅edit到目前为止,我在您的方法中没有看到任何共同点,我不知道您为什么要平等地调用这些方法。@Sulthan方法中的代码在每个类中都是不同的-但是基本函数只在返回类型上有所不同。现在我必须打开单元格的类型才能知道它是哪个elementDataClass。如果我想在顶级类中使用validateModel方法,我可以在每个DataElementClass上调用它,而无需强制转换它。我希望现在更清楚:)非常感谢你的回答。为了避免打开我的单元格类型,然后丢弃数据对象,您有没有其他方法可以遵循?我有点迷路了,因为我不知道如何改进我的课程/模型…@linus_全息图我正在研究,但我花了一段时间来解释effectively@linus_hologram现在查看谢谢您的详细解释。那么,populate方法为单元格返回一个完成的uiview?或者我误解了什么?在我的示例中,TableViewDelegate将单元格出列并传递给模型,以便模型可以填充其数据(通过修改单元格对象,该对象通过引用传递)。在这种情况下返回对象实际上不会实现任何效果。但具体细节并不太重要。您只需要委派填充目标视图(表单元格或其他任何内容)的责任。谢谢您的回答。但是有没有办法将validateModel()方法移动到父类中?子类只覆盖它?因为我遇到的实际问题是,为了访问validateModel(),我希望避免向下转换类?不,不是异构返回类型。别管它!我还没有尝试过,但我认为您的解决方案可以工作。如果我试图将我的类降级为Validatable,则会出现以下错误:“协议‘Validatable’只能用作泛型约束,因为它具有自身或关联的类型要求”。在尝试使用该函数时,我遇到了另一个错误:“成员'validateModel'不能用于协议类型'Validatable'的值;请改用通用约束”如何访问在可验证协议中指定的函数?我不知道您将要完成什么。我的答案是一种我想要的方式