Why is it recommended to prefix property requirements with static in Swift protocols? - swift

In the Swift documentation section about Protocols, it is written that :
Always prefix type property requirements with the static keyword when you define them in a protocol. This rule pertains even though type property requirements can be prefixed with the class or static keyword when implemented by a class
I don't understand if you should always do that or just in specific cases (because later in the docs, static isn't always there).
Why is it recommended to use static? What does it mean concretely?
Thank you.
EDIT : The same question applies to methods requirements.

later in the docs, static isn't always there
This section talks about type requirement, i.e. a requirement of the conforming type to have a static property of the specific name and type. In other words, when you write this
protocol MyProtocol {
static var myProperty: Int { get set }
}
the conforming class must do this
class MyClass : MyProtocol {
static var myProperty: Int
}// ^^^^^^
It also has an option to do this:
class MyClass : MyProtocol {
class var myProperty: Int
}// ^^^^^
but there is no such option when defining a protocol.
When static is not used, as happens later in the docs, the requirement becomes an instance requirement, not a type requirement:
protocol MyProtocol2 {
var myProperty2: Int { get set }
}
Now the class must provide an instance variable:
class MyClass2 : MyProtocol2 {
var myProperty2: Int
}
Note that there is a similar limitation on declaring instance requirements in protocols: you always use var, even though an implementation may use let to satisfy the requirement:
protocol MyProtocol3 {
var myProperty3: Int { get }
}// ^^^
class MyClass3 : MyProtocol3 {
let myProperty3 = 42
}// ^^^

Related

Are protocol methods meant to be overriden in Swift?

I've started working through a textbook that talks about protocol oriented programming in Swift. As I'm writing out the code in a playground I noticed that one of the methods from the book uses the keyword 'static'. To my understanding, a static method means that this method is to be called by the type itself and not by specific instances of the type. Also my understanding is that, static methods can't be overridden.
Since protocols are only method signatures when their being declared, I thought it was kind of odd to see the keyword 'static' being used because we'll have to implement the stub of the function when we conform to the protocol anyway.
To start thinking in an abstract way, I'd like to know if protocol methods are meant to be overridden in Swift or does the use of the keyword 'static' simply makes it to where only the type itself can call a method versus its instances calling the method?
protocol YourProtocol {
//property requirements that types that conform to this protocl MUST implement
var gettableProperty: String { get }
var gettableSettableProperty: Int { get set }
//method requirements that types that conform to this protocol MUST implement
func someMethod(parameter1: Double) -> String
static func staticMethod() -> Float
}
You are right that static methods cannot be overriden because they are always tied to one specific type, however, a static method declaration in a protocol can be implemented using a class method. And class methods can be overriden:
protocol YourProtocol {
static func staticMethod() -> Float
}
class A: YourProtocol {
class func staticMethod() -> Float {
return 1.0
}
}
class B: A {
override class func staticMethod() -> Float {
return 2.0
}
}
Also, the ability to be overriden is not the core point. I think the concept can be better understood on a static constant or a static variable getter, taking an example from the static library:
public protocol FloatingPoint: ... {
public static var pi: Self { get }
}
This protocol is implemented by all floating point types, e.g. Double and Float which are not even classes therefore they don't support inheritance and overriding. The fact that even their static constants are declared in a protocol can be then used when declaring a generic method that uses this protocol as a type constraint:
func toDegrees<T: FloatingPoint>(radians: T) -> T {
// the .pi here is a static var getter
return radians * 180 / T.pi
}

Swift 3: private required initializer possible?

Consider following code:
private class MyClass {
private required init(_ i: Int) {
}
}
Now, I'm getting compiler error:
'required' initializer must be as accessible as its enclosing type. But the type is declared as private.
I thought the issue might be that the class is declared on a file level, so it's
private type
restricts the use of an entity to the enclosing declaration.
as documentation says. So it effectively makes it fileprivate, since the enclosing declaration is a file. But I'm getting the same error even for nested private classes.
When I declare initializer as fileprivate it works:
private class MyClass {
private class MyNested {
fileprivate required init(_ i: Int) {
}
}
}
Question: why private is not correct here? Is it possible to declare private required initializer?
I ask because I want to understand the error in the first place.
Why I need it is rather different question, but initially I wrote such code:
private class MyClass {
private class MyNested {
private init(_ i: Int) {
}
func foo() {
var f = type(of: self).init(1)
}
}
}
and then had to add required declaration specifier as I was getting the error: constructing an object of class type 'MyClass.MyNested' with a metatype value must use a 'required' initializer
Answer:
Thanks to #SørenMortensen:
The issue with the private initialiser is that the MyNested class is accessible within MyClass, but the initialiser is only accessible within MyNested, and therefore is not as accessible as its enclosing type. And as #Hamish points out, the concept of a required initialiser is mutually exclusive with the concept of a private initialiser.
So it looks like it is not possible to have private required initializer, indeed. And in my case I can make MyNested class to be final and then make the initializer private not making it required.
Why would you want one?
The purpose of required means that one is forced to use this initialization when declaring this class. Like #Hamish said, setting it as private would just result in classes unable to see it and cannot declare it. If you want additional setup but don't want it to be accessible, why not just call a private func within a required init?

Statically typed properties in Swift protocols

I'm trying to use Protocol-Oriented Pgrogramming for model layer in my application.
I've started with defining two protocols:
protocol ParseConvertible {
func toParseObject() -> PFObject?
}
protocol HealthKitInitializable {
init?(sample: HKSample)
}
And after implementing first model which conforms to both I've noticed that another model will be basically similar so I wanted to create protocol inheritance with new one:
protocol BasicModel: HealthKitInitializable, ParseConvertible {
var value: AnyObject { get set }
}
A you can see this protocol has one additional thing which is value but I want this value to be type independent... Right now I have models which use Double but who knows what may show up in future. If I leave this with AnyObject I'm sentenced to casting everything I want to use it and if I declare it as Double there's no sense in calling this BasicModel but rather BasicDoubleModel or similar.
Do you have some hints how to achieve this? Or maybe I'm trying to solve this the wrong way?
You probably want to define a protocol with an "associated type",
this is roughly similar to generic types.
From "Associated Types" in the Swift book:
When defining a protocol, it is sometimes useful to declare one or
more associated types as part of the protocol’s definition. An
associated type gives a placeholder name (or alias) to a type that is
used as part of the protocol. The actual type to use for that
associated type is not specified until the protocol is adopted.
Associated types are specified with the typealias keyword.
In your case:
protocol BasicModel: HealthKitInitializable, ParseConvertible {
typealias ValueType
var value: ValueType { get set }
}
Then classes with different types for the value property can
conform to the protocol:
class A : BasicModel {
var value : Int
func toParseObject() -> PFObject? { ... }
required init?(sample: HKSample) { ... }
}
class B : BasicModel {
var value : Double
func toParseObject() -> PFObject? { ... }
required init?(sample: HKSample) { ... }
}
For Swift 2.2/Xcode 7.3 and later, replace typealias in the
protocol definition by associatedtype.

Why always prefix type property requirement with the static keyword in Swift protocol?

On page 369 of the book The Swift Programming Language, it says “Always prefix type property requirements with the static keyword when you define them in a protocol.”
Example Code:
protocol AnotherProtocol {
static var someTypeProperty: Int { get set }
}
What is the reason or benefit of doing so?
Because without the static keyword you end up declaring an instance property rather than a type property. The example that immediately follows the paragraph you quote shows this:
Here’s an example of a protocol with a single instance property requirement:
protocol FullyNamed {
var fullName: String { get }
}

Swift: Class Type does not have member <var>

I have following code snippets:
protocol UpdateUIFromNativeListenerItf {
func triggerUI()
}
class WmBuildGroupsTask{
var mUfn:UpdateUIFromNativeListenerItf?
init(){/* ... */}
// ...
class func triggerRegister( ufn: UpdateUIFromNativeListenerItf ) {
mUfn = ufn // WmBuildGroupsTask.Type does not have `mUfn`
}
}
Form other class I call:
var ufn:UpdateUIFromNativeListenerItf = self
WmBuildGroupsTask.triggerRegister(ufn)
How can I pass delegate to static method?
Do I need create singleton for class WmBuildGroupsTask?
I tried also to write class var mUfn:UpdateUIFromNativeListenerItf?
But get: Class var not yet supported
Thanks,
Static stored properties are not supported in swift classes (yet), but they are in structs. So you can create an inline private struct and define your static properties there:
class WmBuildGroupsTask{
private struct Static {
static var mUfn:UpdateUIFromNativeListenerItf?
}
init(){/* ... */}
// ...
class func triggerRegister( ufn: UpdateUIFromNativeListenerItf ) {
Static.mUfn = ufn // WmBuildGroupsTask.Type does not have `mUfn`
}
}
The downside is that you have to access the static property prefixing it with the struct name - but I guess that's an acceptable tradeoff.
There is also another obvious way to solve the problem: turn the class into a struct, so obvious that it's enough to just mention it. Just a consideration: structs and classes are not interchangeable, they have their own pros and cons.
You are trying to access a member variable in a static context. mUfn is stored for an instance of your class, not for the class itself.