Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

swift: How can I override a public method in superclass to be a private method in subclass

I have a super class

class Father {
    public func doSomething() {
    } 
}

I want this child class to be

class Child: Father {
    private override func doSomething() {
    }
}

but Xcode says that

Overriding instance method must be as accessible as the declaration it overrides

so, how can I override a public method in superclass be a private method in subclass

THANK YOU

like image 207
芮星晨 Avatar asked Apr 16 '16 05:04

芮星晨


People also ask

Can you override a method declared as public in a superclass and declare it private in a subclass?

For example: If the superclass method is declared public then the overriding method in the subclass cannot be either private or protected. Instance methods can be overridden only if they are inherited by the subclass. A method declared final cannot be overridden.

Can a subclass override public methods of a superclass?

A subclass within the same package as the instance's superclass can override any superclass method that is not declared private or final. A subclass in a different package can only override the non-final methods declared public or protected.

Can a public method of a superclass be made private in subclass?

The access specifier for an overriding method can allow more, but not less, access than the overridden method. For example, a protected instance method in the superclass can be made public, but not private, in the subclass.

Can you override a method and make it private?

No, we cannot override private or static methods in Java. Private methods in Java are not visible to any other class which limits their scope to the class in which they are declared.


2 Answers

You can't because that would violate the Liskov Substitution Principle.

Essentially, any code that can operate on an instance of a superclass must also be able to operate on an instance of your subclass.

So, if some other class has a method

class Unrelated {
    func operateOnAThing(_ someThing:Father) {
        someThing.doSomething()
    }
}

then it still has to work when you do the following:

let aChild = Child()

unrelatedInstance.operateOnAThing(aChild)

If the doSomething method had more restrictive access in the Child class then you would get a runtime error. To prevent this, you cannot make access more restrictive in a subclass.

like image 50
Paulw11 Avatar answered Sep 20 '22 13:09

Paulw11


You can achieve that by marking the public method as unavailable using the @available attribute. Then, call the method using super in the private method.

Example:

class Father {
    public func doSomething() {
        print("doSomething privatly")
    }
}

class Child: Father {
    @available (*, unavailable)
    override func doSomething() {
    }

    fileprivate func internal_doSomething() {
        super.doSomething()
    }
}

Child().internal_doSomething()
Child().doSomething() //'doSomething()' has been explicitly marked unavailable

(Tested using Swift 4.0!)

like image 30
ricardopereira Avatar answered Sep 17 '22 13:09

ricardopereira