我可以在 Swift 中获得与 C# 的“受保护”访问类似的最终结果吗?

Posted

技术标签:

【中文标题】我可以在 Swift 中获得与 C# 的“受保护”访问类似的最终结果吗?【英文标题】:I can I get similar end results to "protected" access of C# but in Swift? 【发布时间】:2018-08-26 22:44:14 【问题描述】:

我的目标是编写一个类并在其中包含一个函数,该函数包含要在后台线程中运行的代码(例如在 run() 函数中)。以下是我的班级(及相关班级)的一些要求:

确保当我编写 run() 函数时,代码保证在后台线程中运行,程序员无需了解有关线程的任何信息,也无需记住调用该 run() 函数中相关的任何其他代码到线程。 有一个在其他地方设置的完成函数函数,当后台线程完成其处理时调用它,而程序员不必在此 run() 函数中编写代码来进行调用。 几乎可以让某人从某个基类派生一个类,然后在 run() 函数中编写他们的后台代码,而无需编写与管理后台线程、完成函数等相关的任何其他内容。

这是我可能用 C# 编写的代码,位于两个不同的文件中:

class MyBase

    public Action completionFunction = NULL;
    public void begin()
    
        RunInOtherThread( run ); // This function call is just pseudo-code for running that run() function in a background thread.
        if( completionFunction != Null )
            completionFunction();
    
    virtual protected void run() = 0 // so this class cannot be instantiated
    
    
;

在另一个文件中:

class MySpecificClass : MyBase

    override void run()
    
        // Do important stuff here!
    
;

我不知道如何在 Swift 中满足我的要求。由于对我来说没有意义的原因,他们忽略了“受保护”级别的保护(比如认为我不能仅仅解雇一个通过公共函数公开基类受保护函数来搞砸代码的程序员)。

我对 Swift 的一些特性不够熟悉,无法得到这些结果。我不需要让这些类像 C# 代码一样工作,即使它对我和我的 C# 程序员来说是一个很好的解决方案。

我怎样才能满足我的 Swift 要求?

顺便说一句,我已经看到有关此问题的问答,但没有合理的方法来伪造受保护的访问级别。我不需要伪造它,我只需要另一种方法来实现将代码隐藏在派生类中的目标,除了基类或类似的东西。

【问题讨论】:

【参考方案1】:

我很想为此使用protocols,而不是子分类。例如:

public protocol MyBase 
    // *** This requires any object that conforms to the protocol
    // *** to provide these, without specifying what they do
    var completionFunction: (() -> ())? get set
    func run() 

public extension MyBase 
    // *** This extension provides all objects that conform to the 
    // *** protocol with this function
    func begin() 
        RunInOtherThread( self.run ) // This function call is just pseudo-code for running that run() function in a background thread.
        if let c = self.completionFunction 
            c()
        
    


public class MySpecificClass: MyBase 
    // *** Now, rather than subclassing, we simply conform to the protocol 
    public var completionFunction: (() -> ())? = nil
    public func run()  
        // *** No need to `override` - but *must* be supplied
        // Do important stuff here!
    

【讨论】:

唯一的问题是 run() 函数是公共的,因此使用 MySpecificClass 的人可能会调用它而不是 begin 函数。否则,我可以按原样实现我的类,但使用 public run() 函数。 这是一个很好的例子,说明如何在 Swift 中实现这些类,除了公共的 run() 函数。协议和扩展无疑是处理抽象基类问题的好方法。谢谢。 @DavidRector 您可以尝试提供抽象基类internal init() 并在具体子类中将其覆盖为override public init()。这应该阻止任何人在类层次结构之外实例化基类。它可以编译,但无法测试它在 Playground 中是否有效。当然,它不会强制您覆盖 run(),但您可以将 run internal...

以上是关于我可以在 Swift 中获得与 C# 的“受保护”访问类似的最终结果吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中是不是可以使用内部和受保护的成员? [复制]

在 C# 中,我们可以对接口使用受保护的访问修饰符吗?

如何在 C# 中访问受保护的方法

C# 中的“受保护”方法?

在 C# 问题中访问受密码保护的 MS 访问数据库

在 C# 中调用类的受保护构造函数