Override object method using Swift protocols and extensions - swift

I would like to override a method that is declared in a framework and implemented in an extension.
Here's what I've tried :
import UIKit
// Code from a dependency
class Object { // UIViewController
func printSomething() {
print("something")
}
}
// My code
protocol SayHelloProtocol {
func hello()
func name() -> String
}
extension SayHelloProtocol {
func hello() {
print("Hello " + name())
}
func name() -> String {
"someone"
}
}
class MyHelloObject: Object, SayHelloProtocol {
override func printSomething() {
hello()
}
}
class MyHelloChildObject: MyHelloObject {
func name() -> String {
"You"
}
}
MyHelloObject().printSomething()
MyHelloChildObject().printSomething()
This will print :
Hello someone
Hello someone
But I would like to override the method so it prints :
Hello someone
Hello You
Is it possible to override a method implemented in an extension ?

It works if you add the name() function also to MyHelloObject:
class MyHelloObject: Object, SayHelloProtocol {
override func printSomething() {
hello()
}
func name() -> String {
"Someone"
}
}
class MyHelloChildObject: MyHelloObject {
override func name() -> String {
"You"
}
}

Related

overriding declarations in extensions is not supported - swift

I made a minimal reproducible code of my issue.
enum Animal {
case cat
case dog
}
protocol AdoptPet {
func petIs(pet: Animal)
}
class Delegate {
}
extension Delegate: AdoptPet {
func petIs(pet: Animal) {
print("not implemeted")
}
}
class Girl: Delegate {
}
extension Girl {
override func petIs(pet: Animal) { // overriding declarations in extensions is not supported
print(pet)
}
}
class PetCenter {
init () {
}
func setup(adpoter: Delegate){
let pet: Animal = .cat
adpoter.petIs(pet: pet)
}
}
let petCenter = PetCenter()
let adpoter: Girl = Girl()
petCenter.setup(adpoter: adpoter)
What should I change in the code to make this compile ?
You need to move both the declaration of the function and the override into the type declarations from extensions. So Delegate needs to contain the petIs implementation in its declaration and Girl needs to override the petIs function in its body as well (using the override keyword) rather than in an extension.
class Delegate: AdoptPet {
func petIs(pet: Animal) {
print("not implemeted")
}
}
class Girl: Delegate {
override func petIs(pet: Animal) {
print(pet)
}
}
class PetCenter {
init () {
}
func setup(adopter: Delegate){
let pet: Animal = .cat
adopter.petIs(pet: pet)
}
}
let petCenter = PetCenter()
let adopter = Girl()
petCenter.setup(adopter: adopter) // cat

Call static method without repeating the class name

Is it possible, in Swift, to call a static (or class) method/attribute without writing the class name (from an instance method)?
class Foo {
class func someValue() -> Int {
return 1337
}
func printValue() {
print(Foo.someValue())
print(type(of: self).someValue())
print(Self.someValue()) // error: use of unresolved identifier 'Self'
}
}
So far, I've found a workaround with a protocol / typealias:
protocol _Static {
typealias Static = Self
}
class Foo: _Static {
class func someValue() -> Int {
return 1337
}
func printValue() {
print(Static.someValue()) // 1337
}
}
but I was wondering if there were a better way to do this?
With Swift 5.1 this code no longer produce an error.
class Foo {
class func someValue() -> Int {
return 1337
}
func printValue() {
print(Foo.someValue())
print(type(of: self).someValue())
print(Self.someValue()) // ok
}
}

Method does not override any method from its superclass (Swift 4, Xcode 9)

I've checked few topics related with the same issue but I can't find any solution to this problem inside my own code...
The error occurs when I try to override the function tune() in my Piano: Instrument subclass.
I've copy/past the superclass original function to ensure that the syntax is strictly the same.
Also, it seems to me that the subclass is well done, because the super.init method seems to work as intended (no compiler error).
Please, can someone point out to me where is my error ?
The code :
class Music {
let notes: [String]
init(notes: [String]) {
self.notes = notes
}
func prepared() -> String {
return notes.joined(separator: " ")
}
}
class Instrument {
let model: String
init(model: String) {
self.model = model
func tune() -> String {
fatalError("Implement this method for \(model)")
}
func play(_ music: Music) -> String {
return music.prepared()
}
func perform(_ music: Music) {
print(tune())
print(play(music))
}
}
}
class Piano: Instrument {
let hasPedals: Bool
init(hasPedals: Bool, model: String) {
self.hasPedals = hasPedals
super.init(model: model)
}
override func tune() -> String {
fatalError("Implement this method for \(model)")
}
}
class Guitar: Instrument {
let hasAmplifyer: Bool
init(hasAmplifyer: Bool, model: String) {
self.hasAmplifyer = hasAmplifyer
super.init(model: model)
}
}
Thank you very much !
You have accidentally defined your tune, play, and perform functions inside of your init function. Move them to the top level:
class Instrument {
let model: String
init(model: String) {
self.model = model
}
func tune() -> String {
fatalError("Implement this method for \(model)")
}
func play(_ music: Music) -> String {
return music.prepared()
}
func perform(_ music: Music) {
print(tune())
print(play(music))
}
}
Swift sees no tune function to override because it expects it to be at the top level in Instrument.

Protocol subclass implementation

I have the following code in which I'm trying to force abstraction (abstract class/conformance):
PlayerProtocol:
protocol PlayerProtocol {
func play();
func stop();
func pause();
func getVolume() -> UInt32;
func setVolume(level: UInt32);
func isPaused() -> Bool;
func isStopped() -> Bool;
func onSessionResume();
func onSessionInterupt();
}
BasicPlayer:
class BasicPlayer : PlayerProtocol {
//some variables here..
init() {
//init some variables here..
}
func play() {
fatalError("play() - pure virtual function called.");
}
func stop() {
fatalError("stop() - pure virtual function called.");
}
func pause() {
fatalError("stop() - pure virtual function called.");
}
func getVolume() -> UInt32 {
fatalError("getVolume() - pure virtual function called.");
}
func setVolume(level: UInt32) {
fatalError("setVolume() - pure virtual function called.");
}
func isPaused() -> Bool {
fatalError("isPaused() - pure virtual function called.");
}
func isStopped() -> Bool {
fatalError("isStopped() - pure virtual function called.");
}
func onSessionInterupt() {
fatalError("onSessionInterupt() - pure virtual function called.");
}
func onSessionResume() {
fatalError("onSessionResume() - pure virtual function called.");
}
}
AudioPlayer:
class AudioPlayer : BasicPlayer, PlayerProtocol {
private var device: COpaquePointer = nil;
private var context: COpaquePointer = nil;
private var source: ALuint = 0;
private var buffer: ALuint = 0;
private var interrupted: Bool = false;
private var volume: Float = 50;
override init() {
super.init();
//..
}
deinit {
//..
}
override func play() {
//..
}
override func stop() {
//..
}
override func pause() {
//..
}
override func setVolume(volume: UInt32) {
//..
}
override func getVolume() -> UInt32 {
//..
}
func isPlaying() -> Bool {
//..
}
override func isPaused() -> Bool {
//..
}
override func isStopped() -> Bool {
//..
}
func isAudioPlaying() -> Bool {
return AVAudioSession.sharedInstance().otherAudioPlaying;
}
override func onSessionInterupt() {
self.pause();
}
override func onSessionResume() {
self.play();
}
func setData(buffer: ALuint, source: ALuint) {
self.buffer = buffer;
self.source = source;
}
}
But even though I specified that AudioPlayer implements the PlayerProtocol, it doesn't force me to implement all the member functions like play, stop, etc.. I can remove them and it doesn't complain. It's probably because the super class implements it but I can't figure out how to leave it un-implemented in the super class and allow the derived classes to do the implementation instead.
Basically, BasicPlayer is supposed to be abstract and any class inheriting it must implement "certain" members (not all). OnSessionInterrupt isn't implemented in the derived class. I need it to error.
How can I do this? How can I get it to error at compile time on un-implemented members in the derived classes but not the abstract class?
AudioPlayer is a subclass of a class that already conforms to PlayerProtocol. Because you've implemented all of the methods in the superclass, those implementations are available in your subclass, so you aren't obliged to redeclare them.
It looks to me like you are conceptually abstracting your interface in two separate ways: through a protocol and through an abstract superclass. This might be superfluous? One or the other should be able to serve your purposes.

Subclassing Nested Class in Swift

I'm trying to subclass a nested class as follows:
import Foundation
class Blah {
class BlahNested {
func name() -> String {
return "Blah"
}
}
var blah_ : BlahNested
init() {
blah_ = Blah.BlahNested()
}
func name() -> String {
return blah_.name()
}
}
class SubBlah : Blah {
class BlahNested : Blah.BlahNested {
override func name() -> String {
return "SubBlah"
}
}
init() {
super.init()
blah_ = SubBlah.BlahNested() // THIS LINE IS HAVING ISSUES
}
}
It seems that that nested subclass having the same name as the parent (i.e., "BlahNested" being the same in both the parent and the child) is causing issues. Is it required to have different names in such a case? Thanks!