【问题标题】:How to declare a 'protected' variable in swift如何在 swift 中声明一个“受保护”变量
【发布时间】:2017-06-05 12:29:51
【问题描述】:

我想创建一个继承自另一个类的类,该类位于不同的文件中。

例如:

Class1.swift

class Class1
{
    protected var 
    //Do Stuff
}

Class2.swift

class Class2:Class1
{
    //Do stuff
}

我如何能够在 swift 中访问“受保护”变量/函数?

当我声明一个私有变量/函数时,我只能在那个类中使用它。如果我使用'fileprivate',我的其他类必须与Class1 在同一个文件中。我想要做的是将我的类保存在单独的文件中,并使用 Xcode 中的 Groups 来了解哪个类属于哪个类别。

【问题讨论】:

  • @Sulthan 我看到了那个帖子,因为它没有说任何关于“受保护”的内容。这可能是后来版本的 swift 中添加的东西,或者以不同的方式访问。
  • Xcode 中的组与编译或语言本身无关。这只是对项目中的文件进行逻辑分组的一种方式,与文件系统中的文件夹相同。如果要单独实现,就必须使用modules,即项目中的targets。然后使用internal
  • 我链接的帖子已针对 Swift 3 进行了更新。
  • @我知道这些组。我喜欢在不同的文件中有类,所以我很容易看到每个类等在文件结构中的位置。

标签: swift class swift3 encapsulation


【解决方案1】:

您必须为此使用 internal,因为 Swift 不提供 protected 关键字(与许多其他编程语言不同)。 internalfileprivatepublic 之间的唯一访问修饰符:

内部访问使实体可以在任何源文件中使用 来自他们的定义模块,但不在此之外的任何源文件中 模块。在定义应用程序或 框架的内部结构。

有一个blog post 解释了为什么语言设计者选择不提供protected 关键字(或任何等效关键字)。

其中一些原因

它实际上并没有提供任何真正的保护,因为子类可以 始终通过新的公共方法或属性公开“受保护”的 API。

还有protected 会在涉及扩展时引起问题的事实,因为不清楚扩展是否也应该可以访问protected 属性。

【讨论】:

  • 感谢您的回答。我知道有内部代码,但是由于所有代码都在一个单元中,这意味着我不妨将其公开。
  • @iProgram 但这就是问题所在。您将所有代码集中在一个单元中。
  • 想一想这就是应用程序的发展方向。那么在制作应用程序时,所有东西都应该在不同的单元中吗?如果是这样,这样做的最佳方法是什么?或者是为了另一个主题?虽然我对开发并不陌生,但如果你明白我的意思,我就是。
  • 有几种设计模式,但最常见的是Model-View-Controller
【解决方案2】:

即使 Swift 不提供protected 访问权限,我们仍然可以通过使用fileprivate 访问控制实现类似的访问权限
唯一需要记住的是,我们需要将所有子项声明在与声明的父项相同的文件中。

Animal.swift

import Foundation

class Animal {
    fileprivate var protectedVar: Int = 0
}

class Dog: Animal {
    func doSomething() {
        protectedVar = 1
    }
}

OtherFile.swift

let dog = Dog()
dog.doSomething()

【讨论】:

  • 问题是超类和子类必须在同一个文件中。这将是一个代码设计问题。
  • 没有更好的答案,尽管“继承”是设计者决定不使用的“轴”。唯一实用的解决方案是对实例变量使用文件分离,并智能地使用文件来分离访问控制中省略的“轴”,即 D4ttatraya 提出的。
【解决方案3】:

对这些受保护的变量使用下划线:/

就是这样……

class RawDisplayThing {
    
    var _fraction: CGFloat = 0 {
        didSet { ... }
    }


class FlightMap: RawDisplayThing() {

    var currentPosition() {
        ...
        _fraction = 
        ...
    }
}

每个人都必须“同意”只有概念类才能使用“_”变量和函数。

至少,在每个“_”项上全局搜索并确保它仅由超类使用是相对容易的。

或者,在这些概念前面加上“local”、“display”或类名(或任何对您的团队有意义的名称)。

class RawDisplayThing {
    
    var rawDisplayFraction: ...
    var rawDisplayTrigger: ...
    var rawDisplayConvolution: ...

等等等等。也许有帮助:/

【讨论】:

  • 不明白为什么这种语言还没有提供这么基本的功能。来自 Java/Android,我必须花费数小时寻找 DIY 变通方法,以在我自己的基本 C++ 上制作,例如受保护或抽象类等功能,而许多其他语言刚刚设置了它们(PHP、C#、Java、Kotlin , ..)
  • (FTR 这篇好文章 medium.com/ios-os-x-development/… 确实链接到 Swift Guys's Writing 中他们证明这个问题的确切位置。对我来说,这一切都很糟糕,给我汇编程序 :))跨度>
  • 大声笑,我实际上发现 Java 非常擅长在编译时强制执行规则,这来自于 UML 业务模型。很多语言都只有这些类似 C++ 的特性。事实上 Swift 并没有强迫我花时间重新审视我的 UML 业务逻辑,这非常令人沮丧......
  • 要获得完整的好苹果/坏苹果体验,不妨试试 CoreData!哦,我的..
【解决方案4】:

如果你不想让两个类属于同一个文件,你可以这样做:

class Parent {
    internal private(set) var myProtectedBoolean = false
}

然后在子类上:

class Child: Parent {
   private var _myProtectedBoolean: Bool = false;

   override var myProtectedBoolean: Bool {
       get { return _myProtectedBoolean }
       set { _myProtectedBoolean = newValue }
   }
}

【讨论】:

    【解决方案5】:

    在我看来,下一个最好的办法是将两个类放在同一个文件中,并改用fileprivate

    class Class1 {
       fileprivate var foo: String
    }
    
    final class Class2: Class1 {
       func bar() {
          // Class1.foo is accessible from Class1 but nothing else
          self.foo = "bar" 
       }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-03-23
      • 2012-05-20
      • 2019-11-21
      • 1970-01-01
      • 2017-12-16
      • 2014-04-03
      • 2015-12-29
      • 2012-07-30
      相关资源
      最近更新 更多