协议“Line”只能用作通用约束,因为它具有 Self 或关联类型要求

2024-02-27

我正在快速使用协议。我认为它类似于其他语言中的“界面”。我正在测试它如何处理变量。协议对我来说相当新,因为我从未见过带有非静态变量的接口。我创建了一个车站协议。

protocol Station{
    var id:String {get set}
    var name:String {get set} // station name
    var lines: Array<String> {get set} // all lines persent in this station 
}

然后是包含该车站参考的线路。它还包括 Hashable 协议。

protocol Line: Hashable  {
    var lineId: String{get set}
    var station1:Station {get set}    // start station
    var station2:Station {get set}   // end station
    var stations:Array<Station> {get set}   // all the stations that is in this line   
}

这是该协议的实现

struct LinesImpl: Line{
    var station1: Station
    var station2: Station
    var stations: Array<Station>
    var lineId: String
    static func == (lhs: LinesImpl, rhs: LinesImpl) -> Bool {
        return (lhs.station1.name == rhs.station1.name && lhs.station2.name == rhs.station2.name && lhs.lineId == rhs.lineId)
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(station1.name)
        hasher.combine(station2.name)
        hasher.combine(lineId)
    }
    init(station1: Station, station2: Station, stations: [Station], lineId: String){
        self.station1 = station1
        self.station2 = station2
        self.stations = stations
        self.lineId = lineId   
    }
}

一旦我添加了Hashable。我无法再为 Line 协议创建引用。

当我尝试执行此操作时,它说“协议‘Line’只能用作通用约束,因为它具有自身或关联的类型要求”:

我在这里看到很多类似的问题,但我仍然看不出错误是什么。任何帮助都是极好的。多谢你们。


当你添加Hashable,添加了Equatable,这使得它成为具有关联类型(PAT)的协议,因为Equatable是一个PAT。 PAT 不是一种类型;而是一种类型。它是一个向其他类型添加方法的工具。

您不能使用 PAT 作为变量的类型,不能将其放入数组中,不能直接将其作为参数传递,不能将其作为值返回。 PAT 的唯一一点是作为通用约束(where L: Line)。 PAT 说明了另一个具体类型必须提供什么才能在某些上下文中使用。

您应该如何解决这个问题尚不清楚。这看起来根本不应该是一个协议。这取决于您在这里尝试解决的代码重用问题。

协议通常是关于某物可以做什么do. Line看起来它只是想隐藏实现,而不表达任何内容;这不是一个协议。正如所写的,这里根本没有理由使用泛型或协议。其他实现有什么作用Line看起来像? (我很难想象你还能如何实现这种类型。)

我怀疑正确的答案是将所有这些替换为Station结构体和一个Line结构。我没有看到协议在哪里发挥作用。

这是我可以实现您正在构建的内容的一种方法,以及一些新协议以了解它们的用途。其中一些可能超出了解决此问题所需的范围,但我想展示正在运行的协议。

// A protocol for "ID" types that automatically gives them handy inits
// Nested ID types mean that Line.ID can't get confused with Station.ID.
// The point of a protocol is to add additional features to a type like this.
protocol IDType: Hashable, ExpressibleByStringLiteral, CustomStringConvertible {
    var value: String { get }
    init(value: String)
}

extension IDType {
    // For convenience
    init(_ value: String) { self.init(value: value) }
    // Default impl for ExpressibleByStringLiteral
    init(stringLiteral value: String) { self.init(value: value) }
    // Default impl for CustomStringConvertible
    var description: String { return value }
}

struct Line: Equatable  {
    struct ID: IDType { let value: String }
    let id: ID
    let stations: [Station]
    var origin: Station { return stations.first! } // We ensure during init that stations is non-empty
    var terminus: Station { return stations.last! }

    init(id: ID, origin: Station, stops: [Station], terminus: Station) {
        self.id = id
        self.stations = [origin] + stops + [terminus]
    }
}

// Conforming Line to this protocol lets it print more beautifully.
extension Line: CustomStringConvertible {
    var description: String { return "\(id): \(origin) -> \(terminus)" }
}

// Stations can't contain Line directly. These are value types, and that would be
// recursive. But this is nice because it lets us construct immutable Stations
// and then glue them together with Lines which may even be in independent
// systems (for example, the bus system might be separate from the rail system,
// but share stations)
struct Station: Hashable {
    struct ID: IDType { let value: String }
    let id: ID
    let name: String

    func lines(in system: System) -> [Line] {
        return system.linesVisiting(station: self)
    }
}

extension Station: CustomStringConvertible {
    var description: String { return name }
}

struct System: Equatable {
    let lines: [Line]

    // Using Set here makes it clear there are no duplicates, and saves
    // some hassle turning it back into an Array, but we could also just
    // return Array here as Array(Set(...))
    var stations: Set<Station> {
        // Uniquify the stations
        return Set(lines.flatMap { $0.stations })
    }

    func linesVisiting(station: Station) -> [Line] {
        return lines.filter { $0.stations.contains(station) }
    }
}

// Some examples of using it.
let stationNames = ["Shady Grove", "Bethesda", "Metro Center", "Glenmont",
                    "Wiehle-Reston East", "Largo Town Center"]

// Build up a few stations; obviously there are many more
let stations = Dictionary(uniqueKeysWithValues:
    stationNames.map { ($0, Station(id: .init($0), name: $0)) })

// Define some lines
let redLine = Line(id: "OR",
                   origin: stations["Shady Grove"]!,
                   stops: [stations["Bethesda"]!, stations["Metro Center"]!],
                   terminus: stations["Glenmont"]!)

let silverLine = Line(id: "SV",
                      origin: stations["Wiehle-Reston East"]!,
                      stops: [stations["Metro Center"]!],
                      terminus: stations["Largo Town Center"]!)

// And glue them together into a system
let system = System(lines: [redLine, silverLine])
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

协议“Line”只能用作通用约束,因为它具有 Self 或关联类型要求 的相关文章

  • 点击后退按钮时,iCarousel 会显示在上一页

    当我按下后退按钮时 这iCarousel仍然显示 1 秒 为什么会发生这种情况以及如何阻止这种情况 我已经使用故事板创建了 iCarosel 视图 void viewDidUnload super viewDidUnload self ca
  • Android 和 IOS 是否可以在后台发送短信?

    我想制作一个应用程序 其主要功能取决于发送短信 在我开发 android native 之前 但现在我使用 React Native 来为 IOS 和 Android 制作它 在 Android 中 如果获得用户许可 可以在后台发送短信 但
  • 如何在 Swift 中编写 Cordova 插件?

    我将现有的自定义插件转换为 Swift 语言 位于Plugins CustomPluginInSwift swift import Foundation class CustomPluginInSwift CDVPlugin func ge
  • swift 中带有字符的单引号

    我已经完成了 C C Java 这些语言告诉我字符用单引号括起来 主要是在遵守正确的语法时 但字符串是双引号的 Swift 的语法是否只允许字符位于单引号内 或者提供这种语法背后有一些有效的原因 逻辑 let char1 Character
  • 如果部署目标 < 基础 sdk,如何检查是否使用了不可用的方法?

    我想知道当部署目标低于基础 SDK 时 您如何检查代码是否不调用不可用的方法 可以在 SDK 等于部署目标的设备上运行应用程序 但我搜索一种更 自动 的方式 任何想法 问候 昆汀 最简单的方法是使用 IPHONE OS VERSION MA
  • 当将 contentMode 设置为 UIViewContentModeScaleAspectFit 时,如何设置 UIImageView 左对齐或右对齐?

    我想在使用时控制图像对齐UIViewContentModeScaleAspectFit in UIImageView 例如 我有两个UIImageView在上述的一个视图中 这两个UIImageView的内容模式是UIViewContent
  • 在 Swift async/await 中,我可以使用 Lock 还是 Semaphore

    这不是问题 这是一个想寻求帮助以及专业指导的问题 根据文档 Sendable 类型可以在 Swift Concurrency 中安全地传递 在旧项目中并非所有类型都是可发送的 并且可能使用Cocoa类型 但它们是线程安全的 例如 class
  • 如何在 tvOS 中添加检测按钮按下情况?

    我已经遵循这个tutorial http jamesonquave com blog developing tvos apps for apple tv with swift 一切正常 我遇到的唯一问题是我不知道如何检测何时按下按钮 提前致
  • XCODE:如何从设备获取/验证准确的时间戳

    在没有互联网连接的情况下是否可以获得 NTP 或准确的时间戳 我不能接受 不信任带有 NSDate date 的设备时间戳 因为它可以由用户修改 并且我的应用程序将通过修改系统日期和时间而被黑客攻击 除此之外 是否有任何方法可以检查系统日期
  • 在实现文件中声明接口(Objective-C)

    在上一个版本的 xCode 4 3 中 我看到了预定义模板 例如我们的 Master Detail 模板 其中接口声明是在 m 文件中进行的 例如 在文件 MyFile h 中有 interface MyFile property nona
  • Swift:如何审查/过滤输入的脏话等文本?

    我只是想看看是否有一种既定的方法可以做到这一点 或者如何去做 我有一个文本字段 它本质上充当我的 iOs 应用程序中的表单 用户可以在其中发布内容 我不能让用户发布脏话 不恰当的废话 所以我想过滤掉他们输入的字符串包含这些单词之一的内容并显
  • 从核心数据存储创建 .sqlite 文件?

    我在书籍和提供 sqlite 文件下载的网站上看到过教程 sqlite 文件用于核心数据 如何获取 sqlite 文件FROM应用程序或核心数据存储TO我的桌面 如果您要创建一个预填充的 sqlite 文件以与 Core Data 一起使用
  • 在 SwiftUI App 中实现深色模式切换

    我目前正在我的应用程序中研究深色模式 虽然由于我的 SwiftUI 基础 深色模式本身并不困难 但我正在努力选择将 ColorScheme 设置为独立于系统 ColorScheme 的选项 我在苹果人机界面指南中找到了这一点 https i
  • 使用 Xcode 6 和(可能)cocoapods 生成错误

    在构建使用 cocoapods 和最新 Xcode 6 GM 版本的 iOS 项目时 我收到以下静态分析器错误 error error reading pic error no analyzer checkers are associate
  • SwiftUI ScrollView 只向一个方向滚动

    尝试使用视图作为列表行样式来创建自定义列表 以摆脱默认情况下列表中难看的分隔线 但是 一旦我将 ZStack 行放入滚动视图中 滚动视图就会在两个方向上滚动 而不仅仅是垂直滚动 这是内容视图 NavigationView ScrollVie
  • PreferredInterfaceOrientationForPresentation 必须返回受支持的界面方向 (iOS 6)

    我的应用程序窗口的根视图控制器是 UINavigationController 的子类 我已将此代码添加到类中 BOOL shouldAutorotate return self topViewController shouldAutoro
  • MPMoviePlayerController 播放 YouTube 视频

    如何在 iPhone 上的 MPMoviePlayerController 中播放 YouTube 视频 同时避免进入全屏模式 这个问题已经在这里提出 MPMoviePlayerController 正在播放 YouTube 视频吗 htt
  • 协议本身不符合?

    为什么这段 Swift 代码无法编译 protocol P struct S P let arr P S extension Array where Element P func test
  • 如何将图像放在 UIButton 中文本的右侧?

    如果可以避免的话 我不想使用子视图 我想要一个UIButton其中包含背景图像 文本和图像 现在 当我这样做时 图像位于文本的左侧 背景图像 文本和图像都有不同的高亮状态 最简单的解决方案 iOS 10 及更高版本 Swift button
  • NSRange 到 Range

    我怎样才能转换NSRange to Range

随机推荐

  • Spark 2 的 hbase-spark

    我想要进行全面扫描hbase from Spark 2 using Scala 我没有固定的目录定义 因此库为SHC https github com hortonworks spark shc不是一个选择 我的逻辑选择是使用 hbase
  • Android,如何创建上下文菜单...

    在这里我写了一些代码但没有得到输出 请告诉我为什么不显示该上下文菜单 我在哪里做错了 请指导我 提前谢谢 更多选项卡菜单 xml menu menu
  • Unity 同一物体上的多个碰撞器

    我在同一个游戏对象上使用多个盒子碰撞器 问题是 是否可以使用单独引用每个碰撞器gameObject getComponent enabled false 请记住 我的碰撞器很少 我希望其中一些碰撞器保持启用状态 而其他碰撞器将被禁用 我所做
  • 通过 jest mock 测试 catch 块

    我试图通过玩笑来测试异步 redux 操作的 catch 块 但是在模拟中抛出一个 catch 会导致整个测试失败 我的行动如下 export function loginUser username password return asyn
  • 使用 Google Apps 脚本操作 DOM

    是否可以隐藏 display none 某些标签并使用 Google Apps 脚本更改 Gmail 下拉列表中的标签顺序 标签 移动 不会 Google Apps 脚本在服务器端运行 它无法访问 Gmail Calendar 或 Shee
  • XStream arrayList 与 XML 之间的转换

    我目前不知道问题出在哪里 第一次使用 xml 我在将 ArrayList 放入 xml 文件并从中取出它时遇到了一些问题 我发现了这个 我尝试以同样的方式做 如何使用 XStream 将对象列表转换为 XML 文档 https stacko
  • Python自动选择串口(适用于Arduino)

    目前 Python 程序必须知道设备 Arduino 位于哪个端口 然后 Python 才能与设备进行通信 Problem 每当设备拔出并重新插入时 其 COM 端口都会发生变化 因此必须再次向 Python 提供正确的串行端口 以便它找到
  • 为什么 Android 6 上没有授予 GCM 权限?

    背景 我正在尝试调查办公室的应用程序需要更改其权限 以便更好地支持 Android 6 问题 我发现哪些权限需要确认 哪些不需要 除了以下一项
  • 运行程序所花费的时间

    如何在文本框或输出中打印程序运行时间 我希望将其显示到 for 循环中 以获取每个 for 循环需要多少时间 你可以尝试 DateTime dt DateTime Now for TimeSpan ts DateTime Now dt te
  • 如何使用其他 Angular 组件中的“templateref”?

    如何使用templateRef来自其他组件模板文件 I have BatmanComponent SpidermanComponent and a JokerComponent 其中一些具有相似的功能 因此我决定创建一个HumanCompo
  • Xamarin 自定义表视图标头

    我想在表视图部分标题的标题中添加一个按钮 即加号按钮 经过研究发现 要做到这一点 您必须创建一个自定义标题 我不知道该怎么做 如何在 xamarin 中为表视图部分创建自定义标头 我也使用 Xaml 和 C 请参阅这些博客文章 https
  • 使用自定义字体为警报对话框项目设置字体

    我正在这样创建一个警报对话框 AlertDialog Builder alertDialog new AlertDialog Builder view getContext alertDialog setCustomTitle null a
  • 使用 where 和 offset fetch 子句的简单选择在 Oracle 中不起作用

    我正在尝试选择行where条件并且需要分页 所以我添加了Fetch with offset 使其动态 子句 但随后它给出了此错误 ORA 00933 SQL 命令未正确结束 位置 414 我的查询 SELECT up NAME upozil
  • 是否可以使用ggplot2中的facet_grid()让annotation_logtics()仅出现在一个子图上?

    我使用以下代码在 ggplot2 中使用facet grid 创建一个包含三个子图的图 day lt c 5 Aug 5 Aug 5 Aug 10 Aug 10 Aug 10 Aug 17 Aug 17 Aug 17 Aug station
  • [myArray addObject:[[objcBlock copy] autorelease]] 在释放数组时崩溃

    我编写了一个类来声明性地描述 UIView 动画序列 我的方法采用动画块的可变参数并将它们放入数组中 所以在我的循环中我想这样做 animations addObject block copy autorelease I first cop
  • 正则表达式匹配回句点或字符串开头

    我想匹配一个单词 然后获取它之前的所有内容 直到第一次出现一个句点或字符串的开头 例如 给定此字符串并搜索单词 regex s Do not match this Or this Or this either I like regex It
  • Elasticsearch 不返回单数/复数匹配项

    我正在使用 elasticsearch 的 php 库来索引和查找我的网站中的文档 这是创建索引的代码 curl XPUT http localhost 9200 test d index numberOfShards 1 numberOf
  • 如何在 SVG 中导出 PNG

    我在导出包含 PNG 图像的 SVG 时遇到一些问题 我在用着D3JS和以下代码 mysvg append image attr width 299 attr height 168 attr xlink href image png var
  • Passport.js 支持ajax 吗?

    我想用passport js进行ajax登录 我有设置 Passport js 的常用代码 route app post api auth login passport authenticate local login successRed
  • 协议“Line”只能用作通用约束,因为它具有 Self 或关联类型要求

    我正在快速使用协议 我认为它类似于其他语言中的 界面 我正在测试它如何处理变量 协议对我来说相当新 因为我从未见过带有非静态变量的接口 我创建了一个车站协议 protocol Station var id String get set va