草庐IT

ios - Swift 中任何协议(protocol)的通用约束

coder 2023-09-10 原文

是否可以在 Swift 中限制泛型类型接受协议(protocol)?

我已经实现了包含弱对象列表的包装器,我需要将其扩展到协议(protocol)。

protocol Incrementable: class {
    func inc()
}

class Counter: Incrementable {
    var n: Int = 0

    func inc() {
        n += 1
    }
}

struct Weak<T: AnyObject> {
    weak var value : T?
    init (value: T?)
    {
        self.value = value
    }
}

var cnt: Counter? = Counter()

let counters : [Weak<Counter>] = [Weak(value: cnt), Weak(value: Counter())]

for counter in counters
{
    counter.value?.inc()
}

现在,如果我想存储任何实现Incrementable 的对象,我必须使用AnyObject,这不是很安全并且还包括as? 类型转换

let counters : [Weak<AnyObject>] = [Weak(value: cnt), Weak(value: Counter())]

for counter in counters
{
    (counter.value as? Incrementable)?.inc()
}

我想要的代码是

let counters: [Weak<Incrementable>] = [Weak(value: cnt), Weak(value: Counter())]

for counter in counters
{
    counter.value?.inc()
}

当然,上面的代码无法编译并失败:

Using 'Incrementable' as concrete type conforming to protocol 'AnyObject' is not supported

是否可以编写 Weak 包装器以便它可以接受和存储对协议(protocol)的弱引用?


虽然我的问题的根本原因与 Using as a concrete type conforming to protocol AnyObject is not supported 中的相同该问题涉及哈希表,我需要使用允许重复条目的列表的解决方案。

最佳答案

正在关注 answer为我指明了正确的方向,我能够想出以下解决方案来实现允许重复和 nil(方便)条目的协议(protocol)引用薄弱列表。

struct Weak<T>
{
    weak var value: AnyObject?
    init (value: T?)
    {
        if value != nil
        {
            guard value is AnyObject else { fatalError("Object (\(value)) should be subclass of AnyObject") }
            self.value = value as? AnyObject
        }
    }
}

class WeakList<T>: SequenceType
{
    var items : [Weak<T>] = []

    func add(item: T?)
    {
        items.append(Weak(value: item))
    }

    func generate() -> AnyGenerator<T>
    {
        var nextIndex = items.count - 1

        return anyGenerator
        {
            while nextIndex >= 0
            {
                let item = self.items[nextIndex--]
                if item.value != nil
                {
                   return item.value as? T
                }
            }
            return nil
        }
    }
}

let incrementables = WeakList<Incrementable>()

incrementables.add(Counter())
incrementables.add(cnt)
incrementables.add(nil)
incrementables.add(Counter())
incrementables.add(cnt)

for counter in incrementables
{
    counter.inc()
}

关于ios - Swift 中任何协议(protocol)的通用约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33752315/

有关ios - Swift 中任何协议(protocol)的通用约束的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  3. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  4. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  5. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  6. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  7. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  8. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  9. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

  10. ruby-on-rails - RoR中是否有任何内置方法可以为整数填充零? - 2

    如果我想要“00001”而不是“1”,除了我自己写填零方法之外,有没有内置的方法可以帮助我为整数填零? 最佳答案 puts"%05d"%1#00001参见:String::%,Kernel::sprintf这是正在发生的事情。%左侧的"%05d"是C风格的格式说明符。%右边的变量就是要格式化的东西。格式说明符可以像这样解码:%-格式说明符的开头0-用前导零填充5-长度为5个字符d-被格式化的是一个整数如果你要格式化多个东西,你会把它们放在一个数组中:"%d-%s"%[1,"One"]#=>1-one

随机推荐