Protocol subclass implementation - swift

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.

Related

Injecting a single dependency to a view model

I want the LoginViewModel to have a single dependency of LoginViewModelService.

LoginViewModelService in itself cannot have an implementation.
Its methods will be implemented by both the LoginController and AccountController.
The challenge I’m having right now is, when I instantiate the LoginViewModel which has the single dependency of LoginViewModelService, there is no way I can inject Login Controller and the Account Controller as its implementation class even though they implement the methods of the LoginViewModelService.
To get a better idea I have attached the code from my playground.
What I hope I can do is, there is some way to accomplish the single dependency structure but if thats impossible I would like your recommendation on how I should approach this. Basically my objective is that the service being used by the Login View Model should not have access to method that it does not need, for example Logout() from the Login Controller class or the delete() from the Account controller class.
class AccountController {
func create() {print("Create")}
func get() {print("get")}
func update() {print("update")}
func delete() {print("delete")}
}
// protocol LoginController {
// ...
// }
class LoginController {
func apple() {print("apple")}
func google() {print("google")}
func phone() {print("phone")}
func logout() {print("logout")}
}
protocol LoginViewModelService {
func apple()
func google()
func phone()
func get()
}
extension LoginViewModelService {
func apple(){}
func google(){}
func phone(){}
func get(){}
}
class ViewModel {
init(serivice: LoginViewModelService) {}
}
let accountController = AccountController()
let loginController = LoginController()
extension AccountController: LoginViewModelService {}
extension LoginController: LoginViewModelService {}
// -------------------------This is what I hope I can do-------------
let vm = ViewModel(serivice: accountController & loginController)
// -------------------------------------------------------------------
After playing with it I came up with this solution.
protocol CurrentProfileProvider {
func getMyProfile()
}
protocol ProfileCreator {
func create()
}
protocol ProfileUpdater {
func update(onlyLocally: Bool)
}
protocol ProfileDeleter {
func delete()
}
protocol ConversationCreator {
func create()
}
protocol ListenersProvider {
func listenersList() -> [String]
}
protocol AccountController:CurrentProfileProvider,ProfileCreator,ProfileUpdater,ProfileDeleter {}
class AccountControllerImpl:AccountController {
func update(onlyLocally: Bool) {}
func create() {print("Create")}
func getMyProfile() {print("Get my profile")}
func delete() {print("delete")}
}
protocol LoginProvider {
func apple()
func google()
func phone()
}
protocol Logout {
func logout()
}
protocol AuthenticationController: LoginProvider, Logout {}
class AuthenticationControllerImpl:AuthenticationController {
func apple() {print("apple")}
func google() {print("google")}
func phone() {print("phone")}
func logout() {print("logout")}
}
class ViewModel {
let service: Service
init(service: Service) {
self.service = service
}
}
extension ViewModel {
class Service {
let ac: CurrentProfileProvider
let lc: LoginProvider
init(ac: CurrentProfileProvider, lc: LoginProvider) {
self.ac = ac
self.lc = lc
}
}
}
let ac = AccountControllerImpl()
let lc = AuthenticationControllerImpl()
let service = ViewModel.Service(ac:ac ,lc: lc)
let vm = ViewModel(service: service)

Swift method chaining, how to reuse classes and methods?

Consider the following example
class ClassA {
func createAnInstanceOfAnotherClass() -> AnotherClass {
return AnotherClass()
}
func callMeA() {
}
}
class ClassB {
func createAnInstanceOfAnotherClass() -> AnotherClass {
return AnotherClass()
}
func callMeB() {
}
}
class AnotherClass {
func doSomethingAndReturn() {
return
}
}
class MethodChain {
func methodChainTest() {
ClassA()
.createAnInstanceOfAnotherClass()
.doSomethingAndReturn() //return to ClassA
.callMeA() // call classA callMe
ClassB()
.createAnInstanceOfAnotherClass()
.doSomethingAndReturn() // return to ClassB
.callMeB() // call ClassB callMe
}
}
Is it possible for the class AnotherClass to return the instance of the class that created it?
In this example I want to use the class method doSomethingAndReturn when method chaining with both ClassA and ClassB and then contione the method chain with methods from either ClassA or ClassB
You could make AnotherClass generic with a type parameter Creator, which stores the type of its creator.
class ClassA {
func createAnInstanceOfAnotherClass() -> AnotherClass<ClassA> {
return AnotherClass(creator: self)
}
func callMeA() {
}
}
class ClassB {
func createAnInstanceOfAnotherClass() -> AnotherClass<ClassB> {
return AnotherClass(creator: self)
}
func callMeB() {
}
}
class AnotherClass<Creator: AnyObject> {
// weak to avoid retain cycles!
private weak var creator: Creator?
init(creator: Creator) {
self.creator = creator
}
func doSomethingAndReturn() -> Creator {
// assuming you always do method chaining,
// and not do something weird with the intermediate results,
// this should be safe to unwrap forcefully
creator!
}
}

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
}
}

Swift singleton subclass(inheritance)

I know the simplest way to write singleton in swift is
class A {
static let shared = A()
private init() { //... }
func a() {}
}
// usage
A.shared.a()
the question is that is it possible to write a subclass singleton of class A?
I got the following code from someone to do it by class function
class A {
class func shared() -> A {
private struct _A {
static let _shared = A()
}
return _A.shared
}
func a() { //... }
}
class B: A {
class func shared() -> B {
private struct _B {
static let _shared = B()
}
return _B.shared
}
func b() { //... }
}
// usage
A.shared.a()
B.shared.b()
but the problem is that I can't use private init() to hide initialization here, since there is no protected init() to do this
Does anyone know how to subclass a singleton class by using the private init()?
thanks!
I'm not sure this is a good idea to go down this road. However, if you must, you could keep them in the same file and use fileprivate to accomplish this.
in class A declaration:
fileprivate init() { }
in class B declaration:
override fileprivate init() { }
Good luck!

Can you create a Swift base class that requires its subclasses to implement method(s)? [duplicate]

Is there a way to create an abstract class in the Swift Language, or is this a limitation just like Objective-C? I'd like to create a abstract class comparable to what Java defines as an abstract class.
There are no abstract classes in Swift (just like Objective-C). Your best bet is going to be to use a Protocol, which is like a Java Interface.
With Swift 2.0, you can then add method implementations and calculated property implementations using protocol extensions. Your only restrictions are that you can't provide member variables or constants and there is no dynamic dispatch.
An example of this technique would be:
protocol Employee {
var annualSalary: Int {get}
}
extension Employee {
var biweeklySalary: Int {
return self.annualSalary / 26
}
func logSalary() {
print("$\(self.annualSalary) per year or $\(self.biweeklySalary) biweekly")
}
}
struct SoftwareEngineer: Employee {
var annualSalary: Int
func logSalary() {
print("overridden")
}
}
let sarah = SoftwareEngineer(annualSalary: 100000)
sarah.logSalary() // prints: overridden
(sarah as Employee).logSalary() // prints: $100000 per year or $3846 biweekly
Notice that this is providing "abstract class" like features even for structs, but classes can also implement the same protocol.
Also notice that every class or struct that implements the Employee protocol will have to declare the annualSalary property again.
Most importantly, notice that there is no dynamic dispatch. When logSalary is called on the instance that is stored as a SoftwareEngineer it calls the overridden version of the method. When logSalary is called on the instance after it has been cast to an Employee, it calls the original implementation (it doesn't not dynamically dispatch to the overridden version even though the instance is actually a Software Engineer.
For more information, check great WWDC video about that feature: Building Better Apps with Value Types in Swift
Note that this answer is targeted at Swift 2.0 and above
You can achieve the same behaviour with protocols and protocol extensions.
First, you write a protocol that acts as an interface for all the methods that have to be implemented in all types that conform to it.
protocol Drivable {
var speed: Float { get set }
}
Then you can add default behaviour to all types that conform to it
extension Drivable {
func accelerate(by: Float) {
speed += by
}
}
You can now create new types by implementing Drivable.
struct Car: Drivable {
var speed: Float = 0.0
init() {}
}
let c = Car()
c.accelerate(10)
So basically you get:
Compile time checks that guarantee that all Drivables implement speed
You can implement default-behaviour for all types that conform to Drivable (accelerate)
Drivable is guaranteed not to be instantiated since it's just a protocol
This model actually behaves much more like traits, meaning you can conform to multiple protocols and take on default implementations of any of them, whereas with an abstract superclass you're limited to a simple class hierarchy.
I think this is the closest to Java's abstract or C#'s abstract:
class AbstractClass {
private init() {
}
}
Note that, in order for the private modifiers to work, you must define this class in a separate Swift file.
EDIT: Still, this code doesn't allow to declare an abstract method and thus force its implementation.
The simplest way is to use a call to fatalError("Not Implemented") into the abstract method (not variable) on the protocol extension.
protocol MyInterface {
func myMethod() -> String
}
extension MyInterface {
func myMethod() -> String {
fatalError("Not Implemented")
}
}
class MyConcreteClass: MyInterface {
func myMethod() -> String {
return "The output"
}
}
MyConcreteClass().myMethod()
After I struggled for several weeks, I finally realized how to translate a Java/PHP abstract class to Swift:
public class AbstractClass: NSObject {
internal override init(){}
public func getFoodToEat()->String
{
if(self._iAmHungry())
{
return self._myFavoriteFood();
}else{
return "";
}
}
private func _myFavoriteFood()->String
{
return "Sandwich";
}
internal func _iAmHungry()->Bool
{
fatalError(__FUNCTION__ + "Must be overridden");
return false;
}
}
public class ConcreteClass: AbstractClass, IConcreteClass {
private var _hungry: Bool = false;
public override init() {
super.init();
}
public func starve()->Void
{
self._hungry = true;
}
public override func _iAmHungry()->Bool
{
return self._hungry;
}
}
public protocol IConcreteClass
{
func _iAmHungry()->Bool;
}
class ConcreteClassTest: XCTestCase {
func testExample() {
var concreteClass: ConcreteClass = ConcreteClass();
XCTAssertEqual("", concreteClass.getFoodToEat());
concreteClass.starve();
XCTAssertEqual("Sandwich", concreteClass.getFoodToEat());
}
}
However I think Apple did not implement abstract classes because it generally uses the delegate+protocol pattern instead. For example the same pattern above would be better done like this:
import UIKit
public class GoldenSpoonChild
{
private var delegate: IStomach!;
internal init(){}
internal func setup(delegate: IStomach)
{
self.delegate = delegate;
}
public func getFoodToEat()->String
{
if(self.delegate.iAmHungry())
{
return self._myFavoriteFood();
}else{
return "";
}
}
private func _myFavoriteFood()->String
{
return "Sandwich";
}
}
public class Mother: GoldenSpoonChild, IStomach
{
private var _hungry: Bool = false;
public override init()
{
super.init();
super.setup(self);
}
public func makeFamilyHungry()->Void
{
self._hungry = true;
}
public func iAmHungry()->Bool
{
return self._hungry;
}
}
protocol IStomach
{
func iAmHungry()->Bool;
}
class DelegateTest: XCTestCase {
func testGetFood() {
var concreteClass: Mother = Mother();
XCTAssertEqual("", concreteClass.getFoodToEat());
concreteClass.makeFamilyHungry();
XCTAssertEqual("Sandwich", concreteClass.getFoodToEat());
}
}
I needed this kind of pattern because I wanted to commonize some methods in UITableViewController such as viewWillAppear etc. Was this helpful?
There is a way for simulating abstract classes using Protocols.
This is an example:
protocol MyProtocol {
func doIt()
}
class BaseClass {
weak var myDelegate: MyProtocol?
init() {
...
}
func myFunc() {
...
self.myDelegate?.doIt()
...
}
}
class ChildClass: BaseClass, MyProtocol {
override init(){
super.init()
self.myDelegate = self
}
func doIt() {
// Custom implementation
}
}
One more way how you can implement abstract class is to block initializer.
I've done it this way:
class Element:CALayer { // IT'S ABSTRACT CLASS
override init(){
super.init()
if self.dynamicType === Element.self {
fatalError("Element is abstract class, do not try to create instance of this class")
}
}
}
It's a really old question but still… Here's a snippet of actual code that compiles on Swift 5.2 and works as intended:
protocol Context {
init() throws
func out(_ aStr: String) throws
// Other stuff
}
class AbstractContext: Context {
required init() throws {
if Self.self === AbstractContext.self {
preconditionFailure("Call to abstract method \(Self.self).\(#function)")
}
}
func out(_ aStr: String) throws {
preconditionFailure("Call to abstract method \(Self.self).\(#function)")
}
// Other stuff
}
class CompileContext: AbstractContext {
required init() throws {}
override func out(_ aStr: String) throws {
print(aStr)
}
// Other stuff
}
And here's what I get once I remove CompileContext.out:
Fatal error: Call to abstract method CompileContext.out(_:): file swiftpg/contexts.swift, line 28
With the limitation of no dynamic dispatch, you could do something like this:
import Foundation
protocol foo {
static var instance: foo? { get }
func prt()
}
extension foo {
func prt() {
if Thread.callStackSymbols.count > 30 {
print("super")
} else {
Self.instance?.prt()
}
}
}
class foo1 : foo {
static var instance : foo? = nil
init() {
foo1.instance = self
}
func prt() {
print("foo1")
}
}
class foo2 : foo {
static var instance : foo? = nil
init() {
foo2.instance = self
}
func prt() {
print("foo2")
}
}
class foo3 : foo {
static var instance : foo? = nil
init() {
foo3.instance = self
}
}
var f1 : foo = foo1()
f1.prt()
var f2 : foo = foo2()
f2.prt()
var f3 : foo = foo3()
f3.prt()
I was trying to make a Weather abstract class, but using protocols wasn't ideal since I had to write the same init methods over and over again. Extending the protocol and writing an init method had it's issues, especially since I was using NSObject conforming to NSCoding.
So I came up with this for the NSCoding conformance:
required init?(coder aDecoder: NSCoder) {
guard type(of: self) != Weather.self else {
fatalError("<Weather> This is an abstract class. Use a subclass of `Weather`.")
}
// Initialize...
}
As for init:
fileprivate init(param: Any...) {
// Initialize
}
Move all references to abstract properties and methods of Base class to protocol extension implementation, where Self constraint to Base class. You will gain access to all methods and properties of Base class. Additionally compiler check implementation of abstract methods and properties in protocol for derived classes
protocol Commom:class{
var tableView:UITableView {get};
func update();
}
class Base{
var total:Int = 0;
}
extension Common where Self:Base{
func update(){
total += 1;
tableView.reloadData();
}
}
class Derived:Base,Common{
var tableView:UITableView{
return owner.tableView;
}
}