Swift "nearly matches defaulted requirement" - swift

I have a protocol like this, with some default implementation for the methods:
public protocol BusinessModelTransformable {
func modelId() -> ModelID
func asModelElement(bModel: BusinessModel) -> ModelElement
}
public extension BusinessModelTransformable {
func modelId() -> ModelID { UUID().uuidString }
func asModelElement(bModel: BusinessModel) -> ModelElement {
ModelElement(bModel: bModel, id: self.modelId())
}
}
In another file (of another package if that matters), I do add a conformance to the protocol to a struct, but I don't want the default implement, so I provide my own:
extension ImpDesc: BusinessModelTransformable {
public func modelId() -> ModelID { self.id.uuidString }
public func asModelElement(bModel: BusinessModel) -> ModelElement {
ExtendedModelElement(bModel: bModel,
id: self.id.uuidString,
payload: self)
}
}
I get this warning:
Instance method 'asModelElement(bModel:)' nearly matches defaulted requirement 'asModelElement(bModel:)' of protocol 'BusinessModelTransformable'
only for the asModelElement method.
Why this warning, as this is to me a perfectly valid pattern ?
Why only for the second method ?
how to get rid of that warning () ?

As written by #Joakim Danielson in his comment (many thanks): "while the declarations look the same there is some difference between them", there was indeed a name conflict that was leading to the problem.
Lessons learnt, when the compiler tells you something, that might very well be true.

Related

Can I use a function with generic type inside a protocol extension of that same type?

I have a protocol :
protocol Repository {
associatedtype Element
func getAll() -> Single<[Element]>
}
And a function using this protocol in a generic way :
class Client {
static func fetchCollection<T: Repository>(of params: T) -> Single<[T.Element]> {
[...]
return sendRequest(of: params)
.flatMap({ (response: HTTPURLResponse, jsonData: Data) -> Single<[T.Element]> in
[...]
})
}
}
It works just fine and is really convenient. The getAll() method I need looks like this in 2 examples :
class TypeARepository: Repository {
typealias Element = TypeA
func getAll() -> Single<[Element]> {
return Client.fetchCollection(of: self)
}
}
class TypeBRepository: Repository {
typealias Element = TypeB
func getAll() -> Single<[Element]> {
return Client.fetchCollection(of: self)
}
}
It works, but it's repetitive.
I would like to put the getAll() function inside a protocol extension because I have many objects implementing Repository and it would be cleaner to write it once.
But it does not work and I cannot find a way to fix it :
extension Repository {
func getAll() -> Single<[Element]> {
return Client.fetchCollection(of: self)
}
}
Type of expression is ambiguous without more context
Here is the error (with my names, I simplified them above) :
Any ideas why ? And can it be fixed ?!
but it's repetitive
I don't think you can do anything about that. They are actually completely different methods because the generic placeholder is resolved differently in each case. Thus you cannot "inject" any common implementation.
Thanks for the help
Working through gists helped me find a solution, it's a good way to work I'm happy to have learned that.
https://gist.github.com/Cocatrix/8660a34b28ccac77a9073b204b2ce933
Actually I simplified my code because the Element property itself had an associated property.
The only missing thing to compile was because I wrote Single<Element> instead of Single<Element.Parsable> in the original question.
The error displayed was not clear and I thought it was something similar to what matt discussed https://stackoverflow.com/a/68578593/7490668
It's resolved.

Why does calling a two-argument function require `.self` whereas calling a one-argument function does not? [duplicate]

I've wrote some functions (Swift 2.1, XCode 7.1.1):
public func test1<T:UIView>(type: T.Type) -> T {
print(type.dynamicType)
return type.init()
}
public func test2<T:UIView>(type: T.Type)(_ n: Int) -> T {
print(type.dynamicType)
return type.init()
}
public func test3<T1:UIView, T2:UIView>(type1: T1.Type, _ type2: T2.Type) {
print(type1.init())
print(type2.init())
}
public func test4<T:UIView>(type: T.Type, _ n: Int) {
print(type.init())
print(n)
}
public func test5<T:UIView>(n: Int,_ type: T.Type) {
print(type.init())
print(n)
}
And call them with:
test1(UIButton)
test1(UIButton.self)
test2(UIButton)(1)
test2(UIButton.self)(1)
test3(UIButton.self, UITextField.self)
test4(UIButton.self, 1)
test5(1, UIButton.self)
As you can see, when a type is the only parameter, it can omit the ".self". But for all functions that not have only a type parameter, they require the ".self".
I want to know:
Why is That?
And how to declare a function with multiple parameters that doesn't need ".self" where using it?
Coincidentally, this just came up on swift-evolution. The ability to omit .self when the Type is the only argument, has been reported as a bug in Swift.
The relevant quote from Apple:
It's a bug. .self is supposed to be required everywhere.
Unfortunately, we've had the bug for a while, so I'm not sure how much
code we'd break by changing it. If we wanted to remove the
requirement, that would be considered a language change and would have
to go through the Swift Evolution Process.

Overriding methods in Swift extensions

I tend to only put the necessities (stored properties, initializers) into my class definitions and move everything else into their own extension, kind of like an extension per logical block that I would group with // MARK: as well.
For a UIView subclass for example, I would end up with an extension for layout-related stuff, one for subscribing and handling events and so forth. In these extensions, I inevitably have to override some UIKit methods, e.g. layoutSubviews. I never noticed any issues with this approach -- until today.
Take this class hierarchy for example:
public class C: NSObject {
public func method() { print("C") }
}
public class B: C {
}
extension B {
override public func method() { print("B") }
}
public class A: B {
}
extension A {
override public func method() { print("A") }
}
(A() as A).method()
(A() as B).method()
(A() as C).method()
The output is A B C. That makes little sense to me. I read about Protocol Extensions being statically dispatched, but this ain't a protocol. This is a regular class, and I expect method calls to be dynamically dispatched at runtime. Clearly the call on C should at least be dynamically dispatched and produce C?
If I remove the inheritance from NSObject and make C a root class, the compiler complains saying declarations in extensions cannot override yet, which I read about already. But how does having NSObject as a root class change things?
Moving both overrides into their class declaration produces A A A as expected, moving only B's produces A B B, moving only A's produces C B C, the last of which makes absolutely no sense to me: not even the one statically typed to A produces the A-output any more!
Adding the dynamic keyword to the definition or an override does seem to give me the desired behavior 'from that point in the class hierarchy downwards'...
Let's change our example to something a little less constructed, what actually made me post this question:
public class B: UIView {
}
extension B {
override public func layoutSubviews() { print("B") }
}
public class A: B {
}
extension A {
override public func layoutSubviews() { print("A") }
}
(A() as A).layoutSubviews()
(A() as B).layoutSubviews()
(A() as UIView).layoutSubviews()
We now get A B A. Here I cannot make UIView's layoutSubviews dynamic by any means.
Moving both overrides into their class declaration gets us A A A again, only A's or only B's still gets us A B A. dynamic again solves my problems.
In theory I could add dynamic to all overrides I ever do but I feel like I'm doing something else wrong here.
Is it really wrong to use extensions for grouping code like I do?
Extensions cannot/should not override.
It is not possible to override functionality (like properties or methods) in extensions as documented in Apple's Swift Guide.
Extensions can add new functionality to a type, but they cannot override existing functionality.
Swift Developer Guide
The compiler is allowing you to override in the extension for compatibility with Objective-C. But it's actually violating the language directive.
😊That just reminded me of Isaac Asimov's "Three Laws of Robotics" 🤖
Extensions (syntactic sugar) define independent methods that receive their own arguments. The function that is called for i.e. layoutSubviews depends on the context the compiler knows about when the code is compiled. UIView inherits from UIResponder which inherits from NSObject so the override in the extension is permitted but should not be.
So there's nothing wrong with grouping but you should override in the class not in the extension.
Directive Notes
You can only override a superclass method i.e. load() initialize()in an extension of a subclass if the method is Objective-C compatible.
Therefore we can take a look at why it is allowing you to compile using layoutSubviews.
All Swift apps execute inside the Objective-C runtime except for when using pure Swift-only frameworks which allow for a Swift-only runtime.
As we found out the Objective-C runtime generally calls two class main methods load() and initialize() automatically when initializing classes in your app’s processes.
Regarding the dynamic modifier
From the Apple Developer Library (archive.org)
You can use the dynamic modifier to require that access to members be dynamically dispatched through the Objective-C runtime.
When Swift APIs are imported by the Objective-C runtime, there are no guarantees of dynamic dispatch for properties, methods, subscripts, or initializers. The Swift compiler may still devirtualize or inline member access to optimize the performance of your code, bypassing the Objective-C runtime. 😳
So dynamic can be applied to your layoutSubviews -> UIView Class since it’s represented by Objective-C and access to that member is always used using the Objective-C runtime.
That's why the compiler allowing you to use override and dynamic.
One of the goals of Swift is static dispatching, or rather the reduction of dynamic dispatching. Obj-C however is a very dynamic language. The situation you're seeing is borne out of the link between the 2 languages and the way they work together. It shouldn't really compile.
One of the main points about extensions is that they are for extending, not for replacing / overriding. It's clear from both the name and the documentation that this is the intention. Indeed if you take out the link to Obj-C from your code (remove NSObject as the superclass) it won't compile.
So, the compiler is trying to decide what it can statically dispatch and what it has to dynamically dispatch, and it's falling through a gap because of the Obj-C link in your code. The reason dynamic 'works' is because it's forcing Obj-C linking on everything so it's all always dynamic.
So, it isn't wrong to use extensions for grouping, that's great, but it is wrong to override in extensions. Any overrides should be in the main class itself, and call out to extension points.
There is a way to achieve a clean separation of class signature and implementation (in extensions) while maintaining the ability to have overrides in subclasses. The trick is to use variables in place of the functions
If you make sure to define each subclass in a separate swift source file, you can use computed variables for the overrides while keeping the corresponding implementation cleanly organized in extensions. This will circumvent Swift's "rules" and will make your class's API/signature neatly organized in one place:
// ---------- BaseClass.swift -------------
public class BaseClass
{
public var method1:(Int) -> String { return doMethod1 }
public init() {}
}
// the extension could also be in a separate file
extension BaseClass
{
private func doMethod1(param:Int) -> String { return "BaseClass \(param)" }
}
...
// ---------- ClassA.swift ----------
public class A:BaseClass
{
override public var method1:(Int) -> String { return doMethod1 }
}
// this extension can be in a separate file but not in the same
// file as the BaseClass extension that defines its doMethod1 implementation
extension A
{
private func doMethod1(param:Int) -> String
{
return "A \(param) added to \(super.method1(param))"
}
}
...
// ---------- ClassB.swift ----------
public class B:A
{
override public var method1:(Int) -> String { return doMethod1 }
}
extension B
{
private func doMethod1(param:Int) -> String
{
return "B \(param) added to \(super.method1(param))"
}
}
Each class's extension are able to use the same method names for the implementation because they are private and not visible to each other (as long as they are in separate files).
As you can see inheritance (using the variable name) works properly using super.variablename
BaseClass().method1(123) --> "BaseClass 123"
A().method1(123) --> "A 123 added to BaseClass 123"
B().method1(123) --> "B 123 added to A 123 added to BaseClass 123"
(B() as A).method1(123) --> "B 123 added to A 123 added to BaseClass 123"
(B() as BaseClass).method1(123) --> "B 123 added to A 123 added to BaseClass 123"
This answer it not aimed at the OP, other than the fact that I felt inspired to respond by his statement, "I tend to only put the necessities (stored properties, initializers) into my class definitions and move everything else into their own extension ...". I'm primarily a C# programmer, and in C# one can use partial classes for this purpose. For example, Visual Studio places the UI-related stuff in a separate source file using a partial class, and leaves your main source file uncluttered so you don't have that distraction.
If you search for "swift partial class" you'll find various links where Swift adherents say that Swift doesn't need partial classes because you can use extensions. Interestingly, if you type "swift extension" into the Google search field, its first search suggestion is "swift extension override", and at the moment this Stack Overflow question is the first hit. I take that to mean that problems with (lack of) override capabilities are the most searched-for topic related to Swift extensions, and highlights the fact that Swift extensions can't possibly replace partial classes, at least if you use derived classes in your programming.
Anyway, to cut a long-winded introduction short, I ran into this problem in a situation where I wanted to move some boilerplate / baggage methods out of the main source files for Swift classes that my C#-to-Swift program was generating. After running into the problem of no override allowed for these methods after moving them to extensions, I ended up implementing the following simple-minded workaround. The main Swift source files still contain some tiny stub methods that call the real methods in the extension files, and these extension methods are given unique names to avoid the override problem.
public protocol PCopierSerializable {
static func getFieldTable(mCopier : MCopier) -> FieldTable
static func createObject(initTable : [Int : Any?]) -> Any
func doSerialization(mCopier : MCopier)
}
.
public class SimpleClass : PCopierSerializable {
public var aMember : Int32
public init(
aMember : Int32
) {
self.aMember = aMember
}
public class func getFieldTable(mCopier : MCopier) -> FieldTable {
return getFieldTable_SimpleClass(mCopier: mCopier)
}
public class func createObject(initTable : [Int : Any?]) -> Any {
return createObject_SimpleClass(initTable: initTable)
}
public func doSerialization(mCopier : MCopier) {
doSerialization_SimpleClass(mCopier: mCopier)
}
}
.
extension SimpleClass {
class func getFieldTable_SimpleClass(mCopier : MCopier) -> FieldTable {
var fieldTable : FieldTable = [ : ]
fieldTable[376442881] = { () in try mCopier.getInt32A() } // aMember
return fieldTable
}
class func createObject_SimpleClass(initTable : [Int : Any?]) -> Any {
return SimpleClass(
aMember: initTable[376442881] as! Int32
)
}
func doSerialization_SimpleClass(mCopier : MCopier) {
mCopier.writeBinaryObjectHeader(367620, 1)
mCopier.serializeProperty(376442881, .eInt32, { () in mCopier.putInt32(aMember) } )
}
}
.
public class DerivedClass : SimpleClass {
public var aNewMember : Int32
public init(
aNewMember : Int32,
aMember : Int32
) {
self.aNewMember = aNewMember
super.init(
aMember: aMember
)
}
public class override func getFieldTable(mCopier : MCopier) -> FieldTable {
return getFieldTable_DerivedClass(mCopier: mCopier)
}
public class override func createObject(initTable : [Int : Any?]) -> Any {
return createObject_DerivedClass(initTable: initTable)
}
public override func doSerialization(mCopier : MCopier) {
doSerialization_DerivedClass(mCopier: mCopier)
}
}
.
extension DerivedClass {
class func getFieldTable_DerivedClass(mCopier : MCopier) -> FieldTable {
var fieldTable : FieldTable = [ : ]
fieldTable[376443905] = { () in try mCopier.getInt32A() } // aNewMember
fieldTable[376442881] = { () in try mCopier.getInt32A() } // aMember
return fieldTable
}
class func createObject_DerivedClass(initTable : [Int : Any?]) -> Any {
return DerivedClass(
aNewMember: initTable[376443905] as! Int32,
aMember: initTable[376442881] as! Int32
)
}
func doSerialization_DerivedClass(mCopier : MCopier) {
mCopier.writeBinaryObjectHeader(367621, 2)
mCopier.serializeProperty(376443905, .eInt32, { () in mCopier.putInt32(aNewMember) } )
mCopier.serializeProperty(376442881, .eInt32, { () in mCopier.putInt32(aMember) } )
}
}
Like I said in my introduction, this doesn't really answer the OP's question, but I'm hoping this simple-minded workaround might be helpful to others who wish to move methods from the main source files to extension files and run into the no-override problem.
Use POP (Protocol-Oriented Programming) to override functions in extensions.
protocol AProtocol {
func aFunction()
}
extension AProtocol {
func aFunction() {
print("empty")
}
}
class AClass: AProtocol {
}
extension AClass {
func aFunction() {
print("not empty")
}
}
let cls = AClass()
cls.aFunction()
Just wanted to add that for Objective-C classes, two separate categories can end up overwriting the same method, and it this case... well... unexpected things can happen.
The Objective-C runtime doesn't make any guarantees about which extension will be used, as described by Apple here:
If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime. This is less likely to be an issue if you’re using categories with your own classes, but can cause problems when using categories to add methods to standard Cocoa or Cocoa Touch classes.
It's a good thing Swift prohibits this for pure Swift classes, since this kind of overly-dynamic behaviour is a potential source of hard to detect and investigate bugs.

How can I call a static function on a protocol in a generic way?

Is there a point to declaring a static function on a protocol? The client using the protocol has to call the function on a type conforming to the protocol anyway right? That breaks the idea of not having to know the type conforming to the protocol IMO. Is there a way to call the static function on the protocol in a way where I don't have to know the actual type conforming to my protocol?
Nice question. Here is my humble point of view:
Is there a point to declaring a static function on a protocol?
Pretty much the same as having instance methods declared in a protocol.
The client using the protocol has to call the function on a type conforming to the protocol anyway right?
Yes, exactly like instance functions.
That breaks the idea of not having to know the type conforming to the protocol IMO.
Nope. Look at the following code:
protocol Feline {
var name: String { get }
static func createRandomFeline() -> Feline
init()
}
extension Feline {
static func createRandomFeline() -> Feline {
return arc4random_uniform(2) > 0 ? Tiger() : Leopard()
}
}
class Tiger: Feline {
let name = "Tiger"
required init() {}
}
class Leopard: Feline {
let name = "Leopard"
required init() {}
}
let feline: Feline = arc4random_uniform(2) > 0 ? Tiger() : Leopard()
let anotherFeline = feline.dynamicType.createRandomFeline()
I don't know the real type inside the variable feline. I just know that it does conform to Feline. However I am invoking a static protocol method.
Is there a better way to do this?
I see, you would like to call a static method/function declared in a protocol without creating a value that conforms to the protocol.
Something like this:
Feline.createRandomFeline() // DANGER: compiler is not happy now
Honestly I don't know the reason why this is not possible.
yes this is possible:
Swift 3
protocol Thing {
static func genericFunction()
}
//... in another file
var things:[Thing] = []
for thing in things {
type(of: thing).genericFunction()
}
Thank you #appzYourLife for the help! Your answer inspired my answer.
#appzYourLife answered my question. I had an underlying issue I was trying to resolve and the following code resolves my issue, so I'll post this here, maybe it helps someone with my same underlying question:
protocol MyProtocol {
static func aStaticFunc()
}
class SomeClassThatUsesMyProtocolButDoesntConformToIt {
var myProtocolType: MyProtocol.Type
init(protocolType: MyProtocol.Type) {
myProtocolType = protocolType
}
func aFunction() {
myProtocolType.aStaticFunc()
}
}
I created another solution for this case. IMHO this is quite clean and simple.
First, create a protocol for accessing instance type.
protocol TypeAccessible {
func type() -> Self.Type
}
extension TypeAccessible {
func type() -> Self.Type {
return Swift.type(of: self)
}
}
then create your concrete class as here. The point is your protocol should conform to TypeAccessible protocol.
protocol FooProtocol: TypeAccessible {
static func bar()
}
class Foo: FooProtocol {
static func bar() { }
}
On call site use it as
let instance: FooProtocol = Foo()
instance.type().bar()
For further use cases, just make sure your protocols conform to TypeAccessible and that's all.
A little late to the party on this one.
Here's my solution for "adding" static properties/functions/types to a protocol using typealias.
For example:
enum PropertyScope {
case all
case none
}
struct PropertyNotifications {
static var propertyDidChange =
Notification.Name("propertyDidChangeNotification")
}
protocol Property {
typealias Scope = PropertyScope
typealias Notifications = PropertyNotifications
var scope: Scope { get set }
}
Then you can do this anywhere in your code:
func postNotification() {
let scope: Property.Scope = .all
NotificationCenter.post(name: Property.Notifications.propertyDidChange,
object: scope)
}
Using protocols like Java interfaces is rarely a good idea. They are meta types, meant for defining contracts, which is an entirely different kind of thing.
That being said, just for the point of understanding, I find the most simple and effective way for creating the equivalent of a static factory method of a protocol to write a free function.
It should contain the protocol's name, hoping that that will prevent name clashes, and improve discoverability.
In other languages, createP would be a static member of P, named create and be called as P.create(...), which would drastically improve discoverability and guarantee to prevent name clashes.
In swift, though, this is not an option for protocols, so if protocols are for some reason really actually used as a replacement for interfaces, at least including the protocol's name in the function's name is an ugly workaround that's still slightly better than nothing.
P.S. in case the goal is actually to achieve something like an inheritance hierarchy with structs, union style enums are the tool that's meant to serve that purpose :)
protocol P
{
var x: Int { get }
}
func createP() -> P
{
if (todayIsMonday())
{
return A()
}
else
{
return B()
}
}
class A: P
{
var x = 5
}
class B: P
{
var x = 7
}
This isn't an answer so much as it is an extension to the question. Say I have:
#objc public protocol InteractivelyNameable: Nameable {
static func alertViewForNaming(completion:#escaping((_ success: Bool, _ didCancel: Bool, _ error: Error?) -> Void)) -> UIAlertController?
}
And I have a generic view controller that manages various types (generic type is .fetchableObjectType... basically NSFetchResult). I need to check if a specific object type conforms to the protocol, and if so, invoke it.
something like:
// valid swift code
if self.dataSource.fetchableObjectType is InteractivelyNameable {
// not valid swift code
if let alert = (self.dataSource.fetchableObjectType as InteractivelyNameable).alertViewForNaming(....)
}
I had a situation where I need to create same DomainModel object from 2 different response. so this (static method in protocol helped me) approach helped me.
protocol BaseResponseKeyList: CodingKey {
static func getNameKey()->Self
}
enum FirstResponseKeyList: String, BaseResponseKeyList {
case name
func getNameKey()->FirstResponseKeyList {
return .name
}
}
enum SecondResponseKeyList: String, BaseResponseKeyList {
case userName
func getNameKey()->SecondResponseKeyList {
return .userName
}
}
struct MyDomainModel<T:BaseResponseKeyList> : Decodable {
var name:String?
required init(from d:Decoder) {
do {
let container = try d.container(keyedBy:T.self)
name = try container.decode(String.self, forKey:T.getNameKey())
}catch(_) {
print("error")
}
}
}
let myDomainModel = try JSONDecoder().decode(MyDomainModel <FirstResponseKeyList>.self, from: data)
let myDomainModel2 = try JSONDecoder().decode(MyDomainModel <SecondResponseKeyList>.self, from: data2)

Swift: Generic Protocols

I have some swift structs for which protocol compliance is generated with individual extensions with equal methods names which just differ in their return types which are struct dependent. On top of That I want to use them in a generic function which Calls a protocol conforming function for a generic type).
I tried to accomplish this like that:
//: Playground - noun: a place where people can play
import UIKit
protocol FooProt {
typealias T;
static func createMe<T>()->T;
}
struct FooStruct{
}
extension FooStruct: FooProt{
typealias T = FooStruct;
static func createMe () -> FooStruct{
return FooStruct();
}
}
class Creator{
fun createOne<T where T:FooProt>(type:T.Type){
let instance = T.createMe();
}
}
Unfortunately I get the following error :
/var/folders/sn/78_zvfd15d74dzn01mdv258h0000gq/T/./lldb/3741/playground6.swift:7 :17: note: protocol requires function 'createMe()' with type ' () -> T' (aka '<Ï„_1_0> () -> Ï„_1_0')
static func createMe()->T;
What exactly doesn't comply here and is there a workaround ?
There are several problems with your code. On the one hand you have defined a protocol with an associated type. However, you define your createMe() method as a generic which uses some other type. I don't think that was your intent. I think your intent was to have a createMe() method that returns the same type as the protocol's associated type. In this case you need to remove the from the createMe() method. Also, the name createMe() implies that you aren't just returning any type, but the type of the object on which this method is being called. In this case, you don't even need an associated type protocol. You just need a protocol with a Self constraint which allows your code to be a bit simpler. In your Creator's createOne method, your type constraint is more complex than needed.
I think you want the following code:
protocol FooProt {
static func createMe()->Self;
}
struct FooStruct{
}
extension FooStruct: FooProt {
static func createMe() -> FooStruct {
return FooStruct();
}
}
class Creator{
func createOne<T:FooProt>(type: T.Type) -> T {
return T.createMe()
}
}
let foo = Creator().createOne(FooStruct.self)
Here is an alternate solution using an initializer in the protocol instead of a static method.
protocol FooProt {
init()
}
struct FooStruct{
}
extension FooStruct: FooProt {
}
class Creator{
func createOne<T:FooProt>(type: T.Type) -> T {
return T.init()
}
}
let foo = Creator().createOne(FooStruct.self)