简体   繁体   English

蒸气/流利-在模型中使用协议类型

[英]Vapor / Fluent - Using Protocol Type in a model

I'm experimenting with a server-side-Swift project using Vapor and Fluent. 我正在尝试使用Vapor和Fluent的服务器端Swift项目。 The idea for this project is to track athletes and their training plans and workouts. 该项目的目的是跟踪运动员及其训练计划和锻炼。 Trying to be protocol-oriented, I have a protocol named "Workout," and then various classes that conform to "Workout" such as "run," "swim," etc. 尝试面向协议,我有一个名为“ Workout”的协议,然后有各种符合“ Workout”的类,例如“ run”,“ swim”等。

Workout.swift: Workout.swift:

import Vapor
import FluentPostgreSQL

protocol Workout {
    var title: String { get set }
    var duration: Int { get set }
}

And then, for example, Run.swift: 然后,例如,Run.swift:

import Vapor
import FluentPostgreSQL

final class Run: Workout, Codable {
    //Conform to Workout
    var title: String
    var duration: Int

    //New Properties
    var distance: Double
    var id: Int?

    init(title: String, duration: Int, distance: Double) {
        self.title = title
        self.duration = duration
        self.distance = distance
    }
}

extension Run: PostgreSQLModel {}
extension Run: Content {}

When I create the model for "Training Plan," I would like to have the parameter: 当我为“培训计划”创建模型时,我想使用以下参数:

var workouts = [Workout]?

to allow for any type which conforms to Workout. 允许任何符合Workout的类型。

TrainingPlan.swift: TrainingPlan.swift:

import Vapor
import FluentPostgreSQL

final class TrainingPlan: Codable {
    var id: Int?
    var title: String
    var workouts: [Workout]?

    init(title: String) {
        self.title = title
    }
}

extension TrainingPlan: PostgreSQLModel {}
extension TrainingPlan: Content {}

I get the following errors on TrainingPlan.swift: 我在TrainingPlan.swift上收到以下错误:

Type 'TrainingPlan' does not conform to protocol 'Decodable' 类型“ TrainingPlan”不符合协议“可分解”

Type 'TrainingPlan' does not conform to protocol 'Encodable' 类型“ TrainingPlan”不符合协议“可编码”

Changing Workout.swift to: 将Workout.swift更改为:

protocol Workout: Codable {
    var title: String { get set }
    var duration: Int { get set }
}

does not resolve the errors. 无法解决错误。

What would be the correct way to handle this with Fluent while still staying protocol-oriented in my data modeling? 在我的数据建模中仍然保持面向协议的情况下,用Fluent处理此问题的正确方法是什么? Thank you! 谢谢!

UPDATE (6/20/18): 更新(6/20/18):

Setting a generic type in TrainingPlan.swift (for types that conform to Workout) resolves the errors about conforming to Encodable / Decodable: 在TrainingPlan.swift中设置通用类型(针对符合Workout的类型)可解决有关符合可编码/可解码的错误:

import Vapor
import FluentPostgreSQL

final class TrainingPlan<W: Workout>: Codable {
    var id: Int?
    var title: String
    var workouts: [W]?

    init(title: String) {
        self.title = title
    }
}

extension TrainingPlan: PostgreSQLModel {}
extension TrainingPlan: Content {}
extension TrainingPlan: Parameter {}
extension TrainingPlan: Migration {}

However, this implementation causes another error with adding TrainingPlan to the database migration in configure.swift: 但是,此实现会在将TrainingPlan添加到configure.swift中的数据库迁移中时引起另一个错误:

migrations.add(model: TrainingPlan.self, database: .psql)

Produces the error: 产生错误:

Generic parameter 'W' could not be inferred 无法推断通用参数“ W”

You need to do 你需要做

swift migrations.add(model: TrainingPlan<ConcreteWorkoutType>.self, database: .psql)

So the compiler knows what the generic type is when compiling your code 因此,编译器在编译代码时就知道泛型是什么

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM