【发布时间】:2018-11-27 20:35:36
【问题描述】:
我正在尝试使用 Vapor 和 Fluent 的服务器端 Swift 项目。这个项目的想法是跟踪运动员及其训练计划和锻炼。尝试面向协议,我有一个名为“锻炼”的协议,然后是符合“锻炼”的各种类,例如“跑步”、“游泳”等。
锻炼.swift:
import Vapor
import FluentPostgreSQL
protocol Workout {
var title: String { get set }
var duration: Int { get set }
}
然后,例如 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 {}
当我为“培训计划”创建模型时,我想要参数:
var workouts = [Workout]?
允许任何符合 Workout 的类型。
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 {}
我在 TrainingPlan.swift 上收到以下错误:
类型“TrainingPlan”不符合协议“Decodable”
类型“TrainingPlan”不符合协议“Encodable”
将 Workout.swift 更改为:
protocol Workout: Codable {
var title: String { get set }
var duration: Int { get set }
}
无法解决错误。
在我的数据建模中仍然保持面向协议的同时,使用 Fluent 处理此问题的正确方法是什么?谢谢!
更新(2018 年 6 月 20 日):
在 TrainingPlan.swift 中设置一个泛型类型(对于符合 Workout 的类型)解决了关于符合 Encodable / Decodable 的错误:
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 {}
但是,在 configure.swift 中将 TrainingPlan 添加到数据库迁移时,此实现会导致另一个错误:
migrations.add(model: TrainingPlan.self, database: .psql)
产生错误:
无法推断通用参数“W”
【问题讨论】: