我想在Swift语言中创建一个抽象函数。这是否可行?
class BaseClass {
func abstractFunction() {
// How do I force this function to be overridden?
}
}
class SubClass : BaseClass {
override func abstractFunction() {
// Override
}
}
我想在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
}
}
assert(false, "该方法必须由子类重写")
。 - ErikfatalError("此方法必须被覆盖重写")
- nathanpreconditionFailure("Bla bla bla")
,它会在发布版本中执行,并且也消除了需要使用return语句的必要。编辑:刚刚发现这个方法基本上等同于fatalError()
,但这是更为适当的方式(更好的文档说明,与precondition()
、assert()
和assertionFailure()
一起引入到Swift中,阅读此处)。 - Kametrixom你想要的不是一个基类,而是一个协议。
protocol MyProtocol {
func abstractFunction()
}
class MyClass : MyProtocol {
func abstractFunction() {
}
}
如果在你的类中没有提供abstractFunction,那么就会出现错误。
如果你仍然需要基类来实现其他行为,可以这样做:class MyClass : BaseClass, MyProtocol {
func abstractFunction() {
}
}
这似乎是 Apple 在 UIKit 中处理抽象方法的“官方”方式。
看一下 UITableViewController
以及它与 UITableViewDelegate
的交互方式。你需要做的其中一件事就是添加一行:delegate = self
。好吧,那正是这个技巧。
protocol AbstractMethodsForClassX {
func abstractMethod() -> String
}
/// 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"
}
}
/// 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()
请在Playground中查看输出结果。
UITableViewController
实现UITableViewDelegate
,但仍然需要通过显式地设置delegate
属性来注册委托。getComments
方法。有一些评论类型,我想要与每个对象相关的那些评论。因此,如果我没有覆盖该方法,我希望子类在执行delegate.getComments()
时不会编译。VC只知道它有一个名为delegate
或在您的示例中为BaseClassX
的ParentDelegate
对象,但是BaseClassX
没有抽象化的方法。我需要VC明确知道它正在使用SubclassedDelegate
。 - Jake T.我从一个支持抽象基类的平台移植了相当一部分代码到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={ ..... }
}
}
嗯,我知道我来晚了,可能会利用已经发生的变化。对此感到抱歉。
无论如何,我想贡献我的答案,因为我喜欢测试和使用 fatalError()
的解决方案在我所知道的情况下是无法被测试的,而带有异常的解决方案则更难以测试。
我建议使用更加Swifty的方法。您的目标是定义一个有一些共同细节但没有完全定义的抽象方法,即抽象方法。 使用协议定义抽象中预期的所有方法,既包括已定义的方法,也包括未定义的方法。然后创建一个协议扩展来实现您的情况下定义的方法。 最后,任何派生类必须实现协议,这意味着所有方法都必须实现,但协议扩展中已经有其实现的方法除外。
下面是一个具体函数的示例:
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()
或运行时发生的异常。
protocol BaseProtocol {
func abstractFunction()
}
class SubClass : BaseProtocol {
func abstractFunction() {
// Override
println("Override")
}
}
class SubClass: SuperClass, ProtocolOne, ProtocolTwo {}
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
协议(protocol)
。这个问题还有另一个解决方案,虽然与@jaumard的提议相比仍有不足之处;它需要一个返回语句。尽管我不明白为什么需要它,因为它直接抛出异常:
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();
}
}
AbstractMethodException().raise()
吗? - Joshcodes