swift - 如何在 Swift 中实现 "abstract"属性初始值设定项

标签 swift

到目前为止,我只参与过 Objectiv-C 项目,现在开始了我的第一个 Swift 项目。

我知道 Swift 不支持抽象类,但我想知道在 Swift 中建模/解决这个问题的最佳方法是什么:

// Abstract implementation
public abstract class MyClass {
    private SomeBaseClass someProperty; 

    MyClass() {
        initProperties();
    }

    abstract void initProperties();  // Init someProperty with some child class of SomeBaseClass.
}

// Objectiv-C
@implementation MyClass

- (id)init {
    self = [super init];

    if (self) {
        [self initProperties];     
    }

    return self;
}

- (void)initProperties {
    // Override in inherited classes
}


// Swift
class MyClass {
    // Should not be optional since MyClass should be required to have someProperty != nil
    let someProperty: SomeBaseClass;

    override init() {
        super.init();
        initProperties();
    }

    func initProperties() {
         // Cannot be empty since someProperty is non-optional and needs to be initialized
         // Cannot be empty since Swift does not support abstract methods
    }
}

当然可以将 someProperty 定义为可选的 SomeBaseClass? 但在这种情况下,每次使用该属性时都必须对其进行测试和解包。

有没有更好的办法解决这个问题?

编辑:

我知道 Swift 使用协议(protocol)来创建类似于抽象类的抽象。但是我不明白这个概念如何解决具体问题。

在其他编程语言中,抽象类 MyClass 可以在许多不同的地方使用属性 someProperty,同时留下用其具体子类的值初始化属性的负担。

尽管我阅读了@MohamendS 链接的文章以及对可能的重复答案的回答,但我不明白如何使用协议(protocol)实现相同的目的。

  • MyClass 只有一个抽象 函数,而所有其他函数均已实现。因此 MyClass 本身不能是协议(protocol),因为协议(protocol)不能实现功能(可以吗?)
  • MyClass 只能实现另一个协议(protocol),该协议(protocol)定义必须有一个 initProperties 方法。但在这种情况下,MyClass 需要提供此方法的实现,这让我们回到了同样的问题。

我想我只见树木不见森林,但协议(protocol)在这里有何帮助?

最佳答案

Swift 中的抽象概念与protocols 一起使用,我建议阅读 this文章了解更多,这里是一个例子

 protocol Abstraction {
    var foo: String { get }
    func fee()
    init(with foo: String)
}

class A: Abstraction {

    required init(with foo: String) {
        self.foo = foo 
    }
    var foo: String = ""

    func fee() {

      }
}

编辑:就你的观点而言,

protocols can't implement functions

你不能,但你可以做的是使用扩展来扩展这些协议(protocol),并给它们一个初始实现,因此你不必在类中实现它们,你可以在你想要的时候检查代码如下

    class A: Abstraction {

    required init(with foo: String) {
        self.foo = foo
    }
    var foo: String = ""

    //you don't have to implement func foo anymore as its extended in the extension
}

extension Abstraction {
    func fee() {
        print("ok")
    }
}

let a = A(with: "foo")
a.fee() // this will trigger the extension implementation,

现在要在 extension 正文中使用 init 这样您就不必在每次确认时都键入它们,请查看下面的代码

protocol Abstraction {
    var foo: String { get set }
    func fee()
    init()
    init(with foo: String)
}


class A: Abstraction {
    required init() { }
    var foo: String = ""

    //you don't have to implement func foo anymore as its extended in the extension 
   // you don't have to implement the custom init anymore too 

}

extension Abstraction {
    init(with foo: String) {
        self.init()
        self.foo = foo
    }
    func fee() {
        print("ok")
    }
}

关于swift - 如何在 Swift 中实现 "abstract"属性初始值设定项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55241506/

相关文章:

ios - 无法使用 AVCaptureAudioDataOutputSampleDelegate 播放从语音录制的音频

ios - Swift,检查数组是否在索引处有值

ios - 如何快速复制 float 缓冲区?

ios - 更改 UITableViewCell 中元素的动态高度约束

arrays - 如何通过将一个数组与另一个数组进行比较来从一个数组中删除公共(public)元素

objective-c - 如何创建将处于 DST 模式的 NSDate

ios7 - iOS 7 上的 Swift 字典

ios - 如何使 slider 停止时的当前位置

swift - Swift 中运算符重载的多态性

在调用函数之前快速等待数组设置