草庐IT

ios - 协议(protocol)扩展似乎没有在消费者中强制执行变量?

coder 2023-09-16 原文

说你

protocol Able: class {
    var v:UIView? { get set }
    var x:CGFloat { get set }
}

当然,当你使用 Able 时,

如果您忘记了“v”或“x”...

这是一个错误。那很好。

那么这样做:

class ScreenThing: UIViewController, Able {
    @IBOutlet var v: UIView?
    var x: CGFloat = 0.0
}

一切顺利。太好了。

强制指定“v”和“x”并实际初始化它们。

但是。试试这个...

var _H: UInt8 = 0

protocol Able: class {
}

extension Able where Self:UIViewController {

    var p:P {
    get {
        return objc_getAssociatedObject(self, &_H) as! P
        }
    set {
        objc_setAssociatedObject(self, &_H, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        __setter()
        }
    }
}

Able 现在有一个属性 p。

您可以在 Able 的函数或 ScreenThing 的函数中完美地使用 p。太好了。

然而……

当你这样做的时候......

class ScreenThing: UIViewController, Able {
}

不会收到错误。

您可能会忘记初始化“p”(它会崩溃)。

事实上,您不必将“p”指定为变量(因为您必须指定“v”和“x”)。

为什么会这样?

这似乎是个大问题。

我是否需要做一些不同的事情来让编译器强制执行“p”,就像它通常强制执行协议(protocol)中的变量一样?


看这个问题的另一种方式:

完全按照我上面的代码:

有没有办法强制编译器需要消费者类中“p”的初始值设定项?

例如。

我试过了...

class ScreenThing: UIViewController, Able {
    var p:P
}

但这行不通。

(奇怪的是,编译 - 实际上我不知道它到底在做什么!它似乎是一个与扩展中的 p 不同的 p。但无论如何它不强制执行需要一个初始化程序。)

简而言之,上面有什么我可以做或添加的,这会让编译器强制我初始化伪属性的东西,就像我在协议(protocol)中放置一个属性时它通常会做的那样作为“x”或“v”。

?

  • 也许我必须在协议(protocol)中添加一些普通属性(如“pp”),并以某种方式使 p 与它相关?只是一个想法。

(脚注 -- 请参阅 this 以了解上述协议(protocol)中所需的“: 类”。)


回答我自己的问题:

我上面的困惑是没有什么可以初始化var p:P 在扩展中(带有 get 和 set 代码块)只是两个函数。

没有什么要初始化的。

例如:在我的额外问题中,我问“如何强制符合类在唤醒时对其进行初始化?”那是没有意义的。如果有的话,人们可能会问:“如何强制符合类确保在唤醒时‘使用那些功能’?” - 这与初始化无关。

另请注意,我在计算变量中的特定示例代码恰好(无关地)使用了未初始化的变量 - 导致混淆。

最佳答案

你不必在协议(protocol)的采用者中实现p,因为协议(protocol)扩展已经提供了一个实现。这就是协议(protocol)扩展

更简单的例子:

protocol P {}
extension P {
    func greet() {print("hello")}
}
class C : P {}
C().greet()

请注意 (1) 即使 C 没有声明 greet 也会编译,(2) 即使 C 不包含 greet 的实现它也会运行。那是因为这是协议(protocol)扩展的工作。

关于ios - 协议(protocol)扩展似乎没有在消费者中强制执行变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41796998/

有关ios - 协议(protocol)扩展似乎没有在消费者中强制执行变量?的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  5. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  6. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  7. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  8. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  9. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  10. 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返回它复制的字节数,但是当我还没有下

随机推荐