Inheritance Swift语言中的抽象功能

Inheritance Swift语言中的抽象功能,inheritance,abstract-class,swift,Inheritance,Abstract Class,Swift,我想用swift语言创建一个抽象函数。可能吗 class BaseClass { func abstractFunction() { // How do I force this function to be overridden? } } class SubClass : BaseClass { override func abstractFunction() { // Override } } Swift中没有抽象概念(如O

我想用swift语言创建一个抽象函数。可能吗

class BaseClass {
    func abstractFunction() {
        // How do I force this function to be overridden?
    }
}

class SubClass : BaseClass {
    override func abstractFunction() {
        // Override
    }
}

Swift中没有抽象概念(如Objective-C),但您可以这样做:

class BaseClass {
    func abstractFunction() {
        preconditionFailure("This method must be overridden") 
    } 
}

class SubClass : BaseClass {
     override func abstractFunction() {
         // Override
     } 
}

我明白你现在在做什么,我想你最好还是使用协议

protocol BaseProtocol {
    func abstractFunction()
}
然后,您只需遵守协议:

class SubClass : BaseProtocol {

    func abstractFunction() {
        // Override
        println("Override")
    }
}
如果您的类也是一个子类,则协议遵循超类:

class SubClass: SuperClass, ProtocolOne, ProtocolTwo {}

您需要的不是基类,而是协议

protocol MyProtocol {
    func abstractFunction()
}

class MyClass : MyProtocol {
    func abstractFunction() {
    }
}
如果您的类中没有提供abstractFunction,那就是一个错误

如果其他行为仍然需要基类,可以执行以下操作:

class MyClass : BaseClass, MyProtocol {
    func abstractFunction() {
    }
}

使用
assert
关键字强制执行抽象方法:

class Abstract
{
    func doWork()
    {
        assert(false, "This method must be overriden by the subclass")
    }
}

class Concrete : Abstract
{
    override func doWork()
    {
        println("Did some work!")
    }
}

let abstract = Abstract()
let concrete = Concrete()

abstract.doWork()    // fails
concrete.doWork()    // OK

然而,正如Steve Waddicor所提到的,您可能需要一个
协议来代替

这个问题还有另一个选择,尽管与@jaumard的建议相比,仍然有一个缺点;它需要一个return语句。尽管我忽略了要求它的要点,因为它包含直接抛出异常:

class AbstractMethodException : NSException {

    init() {
        super.init(
            name: "Called an abstract method",
            reason: "All abstract methods must be overriden by subclasses",
            userInfo: nil
        );
    }
}
然后:

class BaseClass {
    func abstractFunction() {
        AbstractMethodException.raise();
    }
}

之后的任何内容都是不可访问的,所以我不明白为什么要强制返回。

我从一个支持抽象基类的平台将大量代码移植到Swift,并大量运行到这个平台。如果您真正想要的是抽象基类的功能,那么这意味着该类既是基于共享的类功能的实现(否则它将只是一个接口/协议),又定义了必须由派生类实现的方法

要在Swift中实现这一点,您需要一个协议和一个基类

protocol Thing
{
    func sharedFunction()
    func abstractFunction()
}

class BaseThing
{
    func sharedFunction()
    {
        println("All classes share this implementation")
    }
}
请注意,基类实现了共享方法,但没有实现协议(因为它没有实现所有方法)

然后在派生类中:

class DerivedThing : BaseThing, Thing 
{
    func abstractFunction() 
    {
        println("Derived classes implement this");
    }
}
派生类从基类继承sharedFunction,帮助它满足协议的这一部分,协议仍然需要派生类来实现abstractFunction

此方法唯一的缺点是,由于基类不实现协议,如果您有一个需要访问协议属性/方法的基类方法,则必须在派生类中重写该属性/方法,并从该基类调用基类(通过super)传递
self
,以便基类有一个协议实例来执行其工作

例如,假设sharedFunction需要调用abstractFunction。协议将保持不变,类现在看起来像:

class BaseThing
{
    func sharedFunction(thing: Thing)
    {
        println("All classes share this implementation")
        thing.abstractFunction()
    }
}

class DerivedThing : BaseThing, Thing 
{
    func sharedFunction()
    {
        super.sharedFunction(self)
    }

    func abstractFunction() 
    {
        println("Derived classes implement this");
    }
}

现在,派生类的sharedFunction满足了协议的这一部分,但是派生类仍然能够以一种相当简单的方式共享基类逻辑。

一种方法是使用基类中定义的可选闭包,子类可以选择是否实现它

class BaseClass {
    var abstractClosure?:(()->())?
    func someFunc()
    {
        if let abstractClosure=abstractClosure
        {
            abstractClosure()
        }
    } 
}

class SubClass : BaseClass {
    init()
    {
        super.init()
        abstractClosure={ ..... }
    }
}

我不知道它是否有用,但我在尝试构建SpritKit游戏时遇到了类似的抽象方法问题。我想要的是一个抽象的动物类,它有move()、run()等方法,但是精灵名称(和其他功能)应该由类的子类提供。因此,我最终做了类似的事情(针对Swift 2进行了测试):


我理解这个问题,并在寻找相同的解决方案。协议与抽象方法不同

在协议中,您需要指定类符合这样的协议,抽象方法意味着您必须重写这样的方法

换句话说,协议是可选的,您需要指定基类和协议,如果您没有指定协议,那么您就不必重写这些方法

抽象方法意味着您需要一个基类,但需要实现自己的一两个方法,这是不同的


我需要同样的行为,这就是为什么我在寻找解决方案。我想斯威夫特错过了这样的功能。

好吧,我知道我比赛迟到了,我可能正在利用已经发生的变化。很抱歉

在任何情况下,我都愿意给出我的答案,因为我喜欢做测试,而且使用
fatalError()
的解决方案是不可测试的,而且带有异常的解决方案更难测试

我建议使用更快速的方法。您的目标是定义一个具有一些公共细节但尚未完全定义的抽象,即抽象方法。使用定义抽象中所有预期方法的协议,包括已定义的方法和未定义的方法。然后创建一个协议扩展来实现案例中定义的方法。最后,任何派生类都必须实现协议,这意味着所有的方法,但是作为协议扩展一部分的方法已经有了它们的实现

用一个具体函数扩展您的示例:

protocol BaseAbstraction {
    func abstractFunction() {
        // How do I force this function to be overridden?
    }
}

extension BaseAbstraction {
    func definedFunction() {
        print("Hello")
}

class SubClass : BaseAbstraction {
    func abstractFunction() {
        // No need to "Override". Just implement.
    }
}
注意,通过这样做,编译器再次成为您的朋友。如果该方法未被“重写”,则在编译时会出现错误,而不是使用
fatalError()
或在运行时出现的异常。这似乎是苹果在UIKit中处理抽象方法的“官方”方式。 查看一下
UITableViewController
及其与
UITableViewDelegate
的工作方式。首先要做的事情之一是添加一行:
delegate=self
。嗯,这正是诀窍

1.将抽象方法放入协议中
protocol AbstractMethodsForClassX {
    func abstractMethod() -> String
}
2.编写你的基类
/// It takes an implementation of the protocol as property (same like the delegate in UITableViewController does)
/// And does not implement the protocol as it does not implement the abstract methods. It has the abstract methods available in the `delegate`
class BaseClassX {
    var delegate: AbstractMethodsForClassX!

    func doSomethingWithAbstractMethod() -> String {
        return delegate.abstractMethod() + " - And I believe it"
    }
}
3.编写子类。 这里是,你如何使用所有这些
let x = ClassX()
x.doSomethingWithAbstractMethod()
检查游乐场以查看输出

一些评论
  • 首先,已经给出了很多答案。我希望有人能找到这个
  • 问题实际上是,找到一种实现以下功能的模式:
    • 类调用一个方法,该方法必须在其派生子类中实现
      /// First and only additional thing you have to do, you must set the "delegate" property
      class ClassX: BaseClassX, AbstractMethodsForClassX {
          override init() {
              super.init()
              delegate = self
          }
      
          func abstractMethod() -> String {return "Yes, this works!"}
      }
      
      let x = ClassX()
      x.doSomethingWithAbstractMethod()