- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我遇到这样一种情况,我在模块中定义了一个可重用的基类,我想提供某些只能由子类而不是该子类的外部用户调用的函数。
我正在编写一个框架并将其打包为 Swift 模块。我的框架的一部分包括一个基类,可以对其进行子类化以添加功能,但是派生类也有更进一步的外部目的。想象一下定义一种新的 View :它派生自 UIView
或 NSView
,然后提供额外的逻辑,然后由另一方实例化。
在这种情况下,我是定义类似于 UIView
的类的人,该类旨在被子类化,并且随之而来的是许多私有(private) UIView
内部东西,比如测量、安排,谁知道呢,内部的东西。
关键是,这个新 View 类的最终用户不想看到支持子类化的体系结构的内部结构,那些应该完全在子类所代表的黑盒子里。
令我震惊的是,这在 Swift 中是不可能的。
我真的不明白为什么 Swift 摆脱了 protected
访问控制。 According to Apple ,我只想公开给子类的函数“在子类之外并不是很有用,所以保护并不重要”。
我错过了什么吗?这是 Swift 根本无法支持的一整类设计模式吗?
我想到的一个想法是,我或许可以将我类(class)的公共(public)-公共(public)和私有(private)-公共(public)部分分成两部分,也许使用协议(protocol),公共(public)-公共(public)用户只能看到公共(public)协议(protocol)和“私有(private)” "公共(public)用户也会看到“私有(private)”协议(protocol)。唉,这似乎是为了过去免费的东西而进行的大量工程。
最佳答案
FWIW — 自从 Swift 中有访问控制之前,我一直在要求在 Swift 中提供更好的访问控制(包括 protected
)。现在,在我们被告知尝试使用 Swift 方法进行访问控制 3.5 年之后,Swift 一直是我近 3 年的主要语言,我仍然认为访问控制范式很笨拙,无法对易于理解的概念进行建模几乎所有相似的语言。
对我来说最大的缓和因素是 Swift 让我在 95% 的时间里不再使用继承和子类化,我认为这是一件好事。所以这个问题出现的次数比其他情况少。但是对于您所描述的情况,没有一种等效的方法可以仅使用协议(protocol)和协议(protocol)扩展来完成您正在做的事情,因此您要么用可能有害的内部细节污染公共(public) API,要么使用一些解决方法(比如下一个)它具有尽可能少的公共(public) API 暴露,并以样板和笨拙为代价模拟您想要的东西。
也就是说,我采用的方法在某种程度上受到了 Objective C 的启发,其中也没有真正的 protected
访问控制,但约定是声明一个公共(public) API header (客户端代码将导入该 header )和引用)和一个特殊的“+Subclassing” header ,只有子类才会在其实现中导入,使它们能够看到非公共(public)消费的内部结构。
在 Swift 中,这也不是直接可能的,但是给定一个这样的类:
open class SomeClass {
private var foo: String
private var bar: Data
public init(){
foo = "foo"
bar = Data()
}
private func doInternalThing() {
print(foo)
}
}
您可以通过扩展添加一个嵌套的“ protected ”包装器(必须与您的类声明在同一个文件中),它采用类(或子类)的实例并将 protected 级别的内部结构公开为一种代理人:
// Create a nested "Protected" type, which can accept an instance of SomeClass (or one of its subclasses) and expose the internal / protected members on it
public extension SomeClass {
public class Protected {
unowned private var someClass: SomeClass
public var foo: String {
get {
return someClass.foo
}
set {
someClass.foo = newValue
}
}
public init(_ someClass: SomeClass) {
self.someClass = someClass
}
public func doInternalThing() {
someClass.doInternalThing()
}
}
}
在框架之外,在客户端应用程序中, protected 成员在这样的子类中访问:
class SomeSubclass: SomeClass {
private lazy var protected: SomeClass.Protected = { SomeClass.Protected(self) }()
func doSomething() {
protected.foo = "newFoo" // Accesses the protected property foo and sets a new value "newFoo"
protected.doInternalThing() // Prints "newFoo" by calling the protected method doInternalThing which prints the foo property.
}
}
这种方法有利也有弊。缺点主要是您需要编写的样板数量,以便将所有属性和函数从 Protected 包装器映射到实际的类实例,如上所示。此外,无法避免这样一个事实,即消费者会将 SomeClass.Protected 视为一种公开可见的类型,但希望很明显它不应该被使用,并且很难随意使用它,所以它不会发生。
优点是在创建子类时没有太多样板文件或给客户带来痛苦,并且很容易声明一个惰性的“ protected ”var 来获得所需的 API。非子类偶然或无意中偶然发现或使用此 API 的可能性很小,而且它大部分是根据需要隐藏的。 SomeSubclass
的实例不会在代码完成或外部代码中显示任何额外的 protected API。
我鼓励任何其他认为访问控制——或者在这种情况下,API 可见性和组织——比现在的 Swift 更容易的人通过 Swift 论坛、Twitter 或 bugs.swift 让 Swift 团队知道。组织。
关于swift - Swift 模块/类如何解决缺少对 "protected"成员的语言支持的问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49097205/
这个问题在这里已经有了答案: How to make a property protected AND internal in C#? (8 个答案) 关闭 9 年前。 我需要声明一个既受又 内部保
我有以下代码: class Base{ protected val alpha ="Alpha"; protected def sayHello = "Hello"; } class
我正在尝试运行一个宏来创建一个工作正常的pdf。 Excel 文件获得签名后,Excel 文件将自动受到保护。 问题:我的工作表上有一个按钮,需要按下该按钮才能创建 pdf 文档网。然而,这是无法完成
子类需要能够使用种子随机数生成器。 使用的优点和缺点是什么 public abstract class AbstractClass { protected Random rnd; public
我们有两个类(class)(A 和 B)。 A类只能由继承它的类创建(A类)B 类可以由用户创建。 A 类,版本 1 有一个private 数据成员,并且有方法访问 A 类中的数据。 A 类,版本 2
当父类受到保护时,我对继承类的默认构造函数有疑问,在我看来,子类也会有一个默认构造函数受到保护,但事实并非如此。 除了在子类上强制默认构造函数外,还有其他方法可以强制保护默认构造函数吗? C++11
我有一个抽象类,我想在其 protected 构造函数中初始化一个只读字段。我希望这个只读字段在派生类中可用。 按照我将所有字段设为私有(private)并公开属性的习惯,我实现如下: abstrac
我在运行大数据时遇到错误。错误已由以下示例示例解释 加载数据 mdata <- as.matrix(read.table('https://gubox.box.com/shared/static
我在获取 时遇到问题非法访问错误 对于以下示例: 我在名为 arch 的 gradle 模块中声明了一个基类 abstract class BaseClass { protected abst
我相信通过 实现 JSF 应用程序的安全性+ + & 通过使用 是两种不同的方式!?他们是吗? 我尝试通过上述第一种方法(使用 + + )来实现安全性,但发现使用 protected 和不
有没有办法确定以下的二传手能见度差异: public Prop { get; protected set; } protected Prop { get; set; } 使用反射?还是那些与 C# 反
我读了一本关于 OOP 的书,并且关于“ protected ”访问修饰符的示例对我来说很奇怪。 例子总结 这个例子是为了测试“protected”保留字对变量的影响。 ClassA 有 2 个 pr
内部——在集会上公开,在其他地方私有(private)。 protected - 只有派生类可以访问父类成员。 Protected internal - protected OR internal -
我有一个类代表 Wicket 中带有“返回”、“前进”和“取消”按钮的基本页面。但并非所有页面都有所有按钮,例如。 G。第一页明显没有“返回”。 我的想法是定义一个通用的ActionHandler p
在了解到嵌套类是嵌套类的成员并因此可以完全访问嵌套类的成员这一事实后(至少对于 C++11,请参见 here),我在尝试创建嵌套类模板: #include using namespace std;
我刚刚使用了 Resharper,并一直在尝试将字段转换为属性。我希望这些属性受到保护,但 Resharper 不想给我这个选项。相反,只有一个 protected 内部选项。这让我思考。要么某处有一
这是 question 的扩展一个小时前问过。 当覆盖派生类中的虚方法时,我们不能修改访问修饰符。考虑 System.Web.UI 命名空间中的 Control 类 public class Cont
有人可以解释一下 C# 中 protected 和 protected internal 修饰符之间的区别吗?看起来他们的行为是相同的。 最佳答案 “protected internal”访问修饰符是
我想知道下面两行代码之间是否有区别: protected $var = null; protected $var; 我已经看到两者都被使用了,我想知道这是否只是一个偏好问题,(也就是 $var; 将变
我正在尝试使用mockito为“另存为”操作编写单元测试。该操作的一部分是制作并显示一个文件对话框,用户可以在其中输入要保存的文件。选择文件不是我可以自动化的操作,因此我想模拟 FileDialog
我是一名优秀的程序员,十分优秀!