【问题标题】:Hiding inner class in swift快速隐藏内部类
【发布时间】:2021-02-25 22:03:14
【问题描述】:

我试图隐藏一个内部类,以便调用者不知道它。如果调用者需要,他们可以使用公共方法获取内部类的实例。但是调用者应该不能直接获取到内部类。

显示我想要的示例:

class A {
    static func getSettings() -> Settings {
        return Settings()
    }
    class Settings {
        func turnOnSomeThing() {
            
        }
    }
}
 
class test {
    func testFunc() {
        A.getSettings().turnOnSomeThing() // correct way of calling
        A.Settings().turnOnSomeThing() // should not be possible
    }
}

这在 Swift 中可行吗?

【问题讨论】:

  • 我认为你要找的是单身
  • class Settings { 987654324 static let shared = Settings() 987654326 print(#function) 987654328 } 987654330 func testFunc() { 987654332 @ // OK Settings().turnOnSomeThing() //错误} }
  • 我希望实例来自外部类的 getter 方法,以便在返回内部类的实例之前执行检查并确保调用成功。
  • 您可以自定义共享实例。如果您不提供实际示例,将很难提供帮助developer.apple.com/documentation/swift/cocoa_design_patterns/…

标签: swift xcode class inner-classes access-control


【解决方案1】:

为什么两个调用都在测试调用者中起作用?

目前两者都有效,因为:

  • 第一种情况,A.getSettings()... 是一个经典的 getter,它返回一个对象。我只是对每次都构造一个新的Settings 感到困惑,但这是完全合法的。
  • 第二种情况,A.Settings()....调用Settings的构造函数来创建一个匿名对象,并在其上调用一些方法。没关系,因为内部类是公开的,但是很奇怪。

你能把内部类设为私有吗?

您可以将内部类设为私有以避免从外部访问它:

  • 这对于外部世界完全不可见的私有助手类非常有效。
  • 对于Settings,这是不可能的,因为getSettings() 会将此类的对象返回给外界,而这只有在外界知道要处理它的类时才有意义。

示例:

class A {
    static func getSettings() -> Settings {   // ERROR if Settings would be private 
        let helper = Helper() // purely internal use: Helper can be private :-)
        helper.demo()
        return Settings()
    }
    class Settings {              // making private is not possible (see above)
        func turnOnSomeThing() {
            print ("On")
        }
    }
    private class Helper {        // Cannot be used outside
       func demo() {
            print ("Demo")
        }
    }
}

但是设置怎么办?

如果您想将Settings 对象返回到外部世界,您需要将该类公开。但是,如果你想避免外部世界误用内部类,避免从外部世界创建对象,你可以在构造函数上使用访问控制:

class A {
    static func getSettings() -> Settings {
        ...
    }
    class Settings {
        fileprivate init() {  /// <===  ACCESS CONTROL internal or fileprivate 
        }
        func turnOnSomeThing() {
            ...
        }
    }
}

这可以防止A.Settings()... 形式的调用,但仅根据 swift access control: 使用internal 您仍然可以从同一模块的另一个文件调用构造函数;使用 fileprivate 只能从您定义了外部类的源文件中调用构造函数。

这种在保持类可用的同时使构造函数不可访问的技术经常用于实例只能通过工厂创建的类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-24
    • 2018-03-14
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 2011-02-14
    • 1970-01-01
    相关资源
    最近更新 更多