Is it possible for protocols to have a default implementation of static factory methods? - swift

Consider a protocol that have a factory method:
public protocol Frobnicator {
func frobnicate()
static func makeRightFrobnicator() -> Frobnicator
}
private class SomeFrobnicatorImplementation: Frobnicator { ... }
private class AnotherFrobnicatorImplementation: Frobnicator { ... }
public extension Frobnicator {
static func makeRightFrobnicator() -> Frobnicator {
if something {
return SomeFrobnicatorImplementation()
} else {
return AnotherFrobnicatorImplementation()
}
}
}
I want to be able to construct different implementors at different times. The implementors themselves are private to the module, whereas the protocol is public to use in the client code.
When I try the code similar to that above, I get “Static member makeRightFrobnicator cannot be used on protocol metatype Frobnicator.Protocol.”
Is there any way around it, or should I just use a free function?

The static function implementation is legal:
protocol P {
static func f() -> P
init()
}
extension P {
static func f() -> P {return self.init()}
}
But you'll notice that in order to get it to compile, I had to guarantee to the compiler that I have in hand a legal way to make a P so as to able to return one.
The issue in your code is the attempt to return a specific adopter of your protocol, like a SomeFrobnicatorImplementation. A protocol is agnostic as to who adopts it. To put it another way, you cannot guarantee within the protocol definition that SomeFrobnicatorImplementation will in fact be an adopter of this protocol. Thus, that part of your code is illegal.

Related

Swift - how to implement protocol methods in function

In android, it is possible to implement interface methods during function call. For example, the declaration of interface and function:
//interface
interface exampleCallback {
void success(String response);
void error(String error);
}
//function
void exampleFunction(exampleCallback cb) {
//do something
}
And the function call:
exampleFunction(new exampleCallback() {
#Override
public void success(String response) {
//custom method implementation
}
#Override
public void error(String error) {
//custom method implementation
}
});
That is, the success/error methods can be customized for each function call of the exampleFunction.
However, after some google search, I can only find example codes for implementing protocol methods in class or struct declaration, in which the methods can no longer be customized. I know I can pass escaping closure as function parameter to achieve the goal, i.e., customize callback function for each function call. But just wonder if I can use protocol to do the similar thing...
You can create an enumeration with associated values:
enum Result {
case success(String)
case error(CustomError)
}
enum CustomError: Error {
case expired(String)
}
And use the enumeration cases in a completion handler of your method to pass your custom string:
func exampleFunction(completion: #escaping (Result) -> ()) {
if condition {
completion(.success("Success String"))
} else {
completion(.error(.expired("Error String")))
}
}
When calling your method you can switch your enumeration and do your custom implementation there as well as use the associated value returned in your callback:
exampleFunction { result in
switch result {
case let .success(response):
// custom method implementation
// use your (response) string here
case let .error(error):
// custom method implementation
// use your (error.localizedDescription) string here
}
}
Playground Sample
Anonymous classes in Java is really just a "workaround" for the absence of functions as "first class citizens".
In swift, functions are first class citizens, so you don't actually need to pass an anonymous class that implements a single method. You just pass that method (somewhat similar to Java 8's lambdas).
This in Java:
interface ActionListener {
void actionPerformed();
}
Can just be represented by a closure type in Swift:
() -> Void
Instead of doing this:
someMethod(new ActionListener() {
public void actionPerformed() { ... }
});
You do this in Swift:
someMethod { ... }
What if your interface in Java has multiple methods to implement?
In that case, you can't use one single closure to represent them all. You need to either
create a protocol with multiple methods and implement it in a struct or class. You see this pattern a lot in UIKit. Views and view controllers often has a XXXDelegate.
pass a tuple of closures

Why we should use struct and class function in singleton pattern?

I'm just reading a code from Udacity learning stuff. The teacher makes an instance variable sharedInstance with a struct that wrapped in a class function
Why can we not simply make a static var?
class BugFactory() {
class func sharedInstance() -> BugFactory {
struct Singleton {
static var sharedInstance = BugFactory()
}
return Singleton.sharedInstance
}
}
Why It's not recommended:
class BugFactory() {
static var sharedInstance = BugFactory()
}
Actually it is recommended to use your second code because of the improvements in the versions of swift.One more thing that you should consider is to declare your singleton object using static let and also make the initializer private
class Bar{
private init(){
// initialization
}
static let shared = Bar()
}
You should actually use static let to create sharedInstance/singleton.
Also make sure to have private init() method, so that any other class does not unintentionally creates another instance of the class which is supposed to singleton.
The tutorial you are referencing might be using some older Swift version. If you have comment options there on video make a comment.

How to port a complicated abstract class to swift?

I have an abstract class in my mind and I can't implement its several features in swift, so I use C++ to deliver my thoughts:
template <class T>
class Swapping {
public:
void swap() { _foregroundIndex = backgroundIndex() }
virtual void cleanup() = 0;
T* foreground() { return _buffer[foregroundIndex()]; }
T* background() { return _buffer[backgroundIndex()]; }
void setForeground(T* foreground) { _buffer[foregroundIndex()] = foreground; }
void setBackground(T* background) { _buffer[backgroundIndex()] = background; }
private:
short foregroundIndex() { return _foregroundIndex; }
short backgroundIndex() { return _foregroundIndex ^ 1; }
short _foregroundIndex = 0;
T* _buffer[2] = {NULL, NULL};
}
The main contradiction is that
The pure virtual method cleanup() requires all subclasses to implement it explicitly (can achieve in swift with protocol)
The instance variable _foregroundIndex has an initial value (cannot achieve using protocol)
The instance variable _foregroundIndex is restricted to be private ( cannot achieve using protocol)
On the other hand, if I use a class instead of protocol, then I can't guarantee cleanup() method is overriden.
One may suggest that put the virtual method in a protocol and the instance variable in a class. That may work but is not a obsession-satisfying one.
P.S. Objective-C is not Swift. Any objc_runtime related workaround is not preferred.
There’s an obvious solution, which I have seen often but will certainly not satisfy you is:
func cleanup() {
fatalError("You must override cleanup()")
}
Then you could try using extensions to extend the protocol with default implementations, but extensions don’t allow stored properties and so you would most likely need some external objects or other magic you certainly also dislike.
As I noted above in the comments, you might need to rethink your design. I don’t know what you really intend to do, but maybe something like this would work out for you:
class Swapper<T> {
private var foregroundIndex = 0
private var backgroundIndex: Int {
return foregroundIndex ^ 1
}
private var buffer: [T?] = [nil, nil]
private let cleanupHandler: () -> ()
init(cleanupHandler: #escaping () -> ()) {
self.cleanupHandler = cleanupHandler
}
func cleanup() {
cleanupHandler()
}
var foreground: T? {
get {
return buffer[foregroundIndex]
}
set {
buffer[foregroundIndex] = newValue
}
}
var background: T? {
get {
return buffer[backgroundIndex]
}
set {
buffer[backgroundIndex] = newValue
}
}
func swap() {
foregroundIndex = backgroundIndex
}
}
This makes more sense to me as this allows any types to be swapped with any clean up handler, without having to subclass the class every time.

Public Extensions in Swift : Float vs Float.type

I'm trying to build an extension for floats in Swift that returns an enum (case .Positive for positive, .Negative for negative). I built an enum first.
public enum Sign
{
case Positive,Negative
}
Now, for the extension,
public extension Float
{
public static func sign()-> Sign
{
if self < Float(0)
{
return Sign.Negative
}
else
{
return Sign.Positive
}
}
}
I'm getting
Cannot convert value of type 'Float.Type' to expected argument type
For the line
if self < Float(0)
But that shouldn't be happening, considering that 'self' inside an extension for Float, should remain a float.
Because you are using static:
public static func sign()-> Sign { ... }
self in this function refers to the type (the Float struct) rather than the instance (a floating point number). Remove the static and you'll be fine.
First thing you are using it with static as #codedifferent already explained and second if there is already a property isMinus then why are using your own logic?
Simply use this to reduce number of lines of code:
public extension Float {
public func sign()-> Sign {
return self.isSignMinus ? Sign.Negative : Sign.Positive
}
}

How to execute once when module loads?

I need to create objects from string names that I am reading from a script. I don't want to use the Objective-C runtime.
In my C++ implementation, each class registered itself with an object factory singleton through a global static variable. When the dll loads, the globals were initialized, and all available classes were registered.
I don't want the object factory to have hard coded pre-knowledge of all possible types.
In Swift, all globals are lazily initialized so my C++ registration strategy doesn't work.
Is there some init API that swift calls once per module load?
If not, does anyone have a good idea for class registration?
public enum DynamicTypeFactoryError : ErrorType {
case ClassNotRegistered
}
public protocol DynamicType {
static var dynamicClassName: String { get }
init()
}
public struct DynamicTypeRegistraion<T: DynamicType> {
public init() {
DynamicTypeFactory.inst.register(T.dynamicClassName, factory: { T() })
}
}
//===========================================================================
// singleton
public class DynamicTypeFactory {
// properties
public static let inst = DynamicTypeFactory()
typealias ClassFactoryType = (Void) -> DynamicType
var registry = [String : ClassFactoryType]()
// methods
public func create(className: String) throws -> DynamicType {
// make sure the class exists
guard let factory = registry[className] else {
throw DynamicTypeFactoryError.ClassNotRegistered
}
return factory()
}
/// This is used to register an object so it can be dynamically created
/// from a string.
public func register(className: String, factory: (Void) -> DynamicType) {
if (registry[className]) != nil {
// TODO - this should be logged
assertionFailure("Class: \(className) is already registered")
} else {
registry[className] = factory
}
}
}
//===========================================================================
// MyObject
public struct MyObject : DynamicType {
// properties
static let registration = DynamicTypeRegistraion<MyObject>()
public static var dynamicClassName = "MyObject"
public init() {
}
}
// Usage
let myObj = try? DynamicTypeFactory.inst.create("MyObject")
Since MyObject's static registration is not initialized, calling create fails because it hasn't been registered yet.
After reviewing the links posted by Martin R, it appears there is no "non-lazy" initialization of statics, and this is by design. So a different approach will be needed for Swift applications. Thanks Martin!
There are two methods in Objective C which are used to load and initialize a class.
+load and +initialize
1. In swift you can use "public override class func initialize()" to put your initialization code, please note that it will be called lazily.
Support for overriding load was removed in Swift 1.2
Here is what docs say about initialize method
"The runtime sends initialize to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program. The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses."