Type 'T' does not conform to protocol 'EntityType' - swift

I think the type relationships are rather plain here and yet I'm missing the cause for the error. The error is: "Type 'T' does not conform to protocol 'EntityType'" (at ThingManager):
//
protocol EntityType {
typealias Identifier
var identifier : Identifier { get }
}
class EntityWithStringIdentifier : EntityType {
var identifier : String
init (i:String) { self.identifier = i }
}
class Thing : EntityWithStringIdentifier {}
//
protocol EntityManager {
typealias Entity : EntityType
func has (entity:Entity) -> Bool
}
class BaseEntityManager<Entity:EntityType> : EntityManager {
func has (entity:Entity) -> Bool { return true }
}
// Type 'T' does not conform to protocol 'EntityType'
class ThingManager<T:Thing> : BaseEntityManager<T> {
}
T is a subtype of Thing; Thing is a subtype of EntityWithStringIdentifier which implements EntityType. So, why the error?
Apparently the error is avoidable by using:
class ThingManager<T:Thing where T:EntityType> : BaseEntityManager<T> {
}
and then one can instantiate a ThingManager with Thing (implying Thing implemented EntityType in the first place...)
var tm = ThingManager<Thing>()
From a type perspective, is there a better way to implement this kind of DAO pattern?

With the announcement of Swift 2.0, it seems pointless to answer this question in terms of earlier versions of Swift, which will very soon be obsolete. I can confirm that this problem—which I believe to be a bug—still exists as of this writing in Swift 2.0. However, I can suggest a slightly different way to organize the code that mitigates the problem while still having a clean implementation: Skip the ThingManager class and use a protocol extension instead.
So, leaving all your code the same up to BaseEntityManager, you'd have:
// NOTE "where Entity: Thing". This is the key.
extension EntityManager where Entity: Thing {
func useAThing(thing: Thing) {
}
}
let tm = BaseEntityManager<Thing>()
tm.useAThing(Thing(i: "thing"))
I suspect this will end up being the "Swift way" of doing things. Swift's generics are just plain strange to me. They constantly violate the Principle of Least Surprise, IMHO. But ultimately they are quite powerful if you learn their quirks. The only drawback of this approach is with access modifiers and encapsulation. The useAThing method has no access to the private state of EntityManagerBase, which may or may not be a problem depending on your circumstances.
Lastly, if you take this approach, I recommend some renaming. BaseEntityManager feels like the wrong name if you never subclass it. Instead, I would call it EntityManager and rename the protocol to EntityManagerType to follow Apple's conventions.

Related

Do not understand "Member '<func>' cannot be used on value of type 'any <type>'; consider using a generic constraint instead" error

Having a problem with a protocol & generics that I am just not able to quite get a handle on.
In the code below, marked by ERROR HERE comment, I am getting the following error:
Member 'protocolMethod' cannot be used on value of type 'any Protocol1'; consider using a generic constraint instead
I assume it is complaining mainly because of the type of the item parameter is at least in some way unresolved? And I am unfortunately not finding the suggestion helpful as I don't see how a generic constraint is going to help here (at least to my understanding of them).
Honestly I kind of feel like I might just be asking too much of Swift here.
Anybody perhaps see what the problem is or have suggestions for trying to resolve this?
Added 12/26/22 - As further background, what caused the error to appear was adding the item param to the protocolMethod method on the protocol, which pretty much shows it is the core of the issue.
protocol Protocol1
{
associatedtype DataItem
func protocolMethod(item : DataItem)
}
protocol Protocol2 {
associatedtype AType1: Hashable
//...
}
class Class1<Type1: Protocol2>: NSObject
{
typealias Item = Type1.AType1
var delegate : (any Protocol1)?
private func method1(item: Item)
{
delegate?.protocolMethod(item : item) //ERROR HERE
}
}
(using latest Xcode)
You get this error because when you write:
var delegate : (any Protocol1)?
You don't give the compiler about what DataItem is. It can be anything, and it should not matter in your Class1 implementation.
But when you write:
private func method1(item: Item)
{
delegate?.protocolMethod(item : item) //ERROR HERE
}
You are trying to pass an object of type Type1.AType1 as an argument of a method that expects a DataItem, and since delegate can be any Protocol1 you have no guarantee that they are the same.
The error message actually proposes a solution:
Member 'protocolMethod' cannot be used on value of type 'any Protocol1'; consider using a generic constraint instead
You could add another type parameter to Class1 and add a generic constraint to tell the compiler that the AType1 and DataItem need to be equal:
class Class1<Type1: Protocol1, Type2: Protocol2>: NSObject where Type1.DataItem == Type2.AType1
{
typealias Item = Type2.AType1
var delegate : Type1?
private func method1(item: Item)
{
delegate?.protocolMethod(item : item)
}
}

Swift Generics - Attempting to make a generic protocol concrete fails when attempting to use specialised sub-protocol as variable

I want to know why my SomeResourceRepository is still generic, even though it is only defined in one case only, which is when I set ResourceType = SomeResource, which XCode formats as below with the where clause. Code below which shows the exact setup I'm trying to achieve, written in a Playground.
I am trying to define a generic protocol for any given ResourceType such that the ResourceTypeRepository protocol then automatically requires the same set of functions, without having to copy-paste most of GenericRepository only to manually fill in the ResourceType for each Repository I make. The reason I need this as a protocol is because I want to be able to mock this for testing purposes later. So I'll provide an implementation of said protocol somewhere else in the actual app.
My interpretation of the code below is that it should work, because both SomeResourceLocalRepository and SomeResourceRemoteRepository are concrete, as I have eliminated the associated type by defining them "on top of" SomeResourceRepository, which is only defined where ResourceType == SomeResource.
import Foundation
struct SomeResource: Identifiable {
let id: String
let name: String
}
struct WhateverResource: Identifiable {
let id: UUID
let count: UInt
}
protocol GenericRepository: class where ResourceType: Identifiable {
associatedtype ResourceType
func index() -> Array<ResourceType>
func show(id: ResourceType.ID) -> ResourceType?
func update(resource: ResourceType)
func delete(id: ResourceType.ID)
}
protocol SomeResourceRepository: GenericRepository where ResourceType == SomeResource {}
protocol SomeResourceLocalRepository: SomeResourceRepository {}
protocol SomeResourceRemoteRepository: SomeResourceRepository {}
class SomeResourceLocalRepositoryImplementation: SomeResourceLocalRepository {
func index() -> Array<SomeResource> {
return []
}
func show(id: String) -> SomeResource? {
return nil
}
func update(resource: SomeResource) {
}
func delete(id: String) {
}
}
class SomeResourceService {
let local: SomeResourceLocalRepository
init(local: SomeResourceLocalRepository) {
self.local = local
}
}
// Some Dip code somewhere
// container.register(.singleton) { SomeResourceLocalRepositoryImplementation() as SomeResourceLocalRepository }
Errors:
error: Generic Protocols.xcplaygroundpage:45:16: error: protocol 'SomeResourceLocalRepository' can only be used as a generic constraint because it has Self or associated type requirements
let local: SomeResourceLocalRepository
^
error: Generic Protocols.xcplaygroundpage:47:17: error: protocol 'SomeResourceLocalRepository' can only be used as a generic constraint because it has Self or associated type requirements
init(local: SomeResourceLocalRepository) {
I will probably have to find another way to accomplish this, but it is tedious and quite annoying as we will produce a lot of duplicate code, and when we decide to change the API of our repositories, we will have to manually change it for all the protocols as we don't follow a generic "parent" protocol in this work-around.
I have read How to pass protocol with associated type as parameter in Swift and the related question found in an answer to this question, as well as Specializing Generic Protocol and others.
I feel like this should work, but it does not. The end goal is a concrete protocol that can be used for dependency injection, e.g. container.register(.singleton) { ProtocolImplementation() as Protocol } as per Dip - A simple Dependency Injection Container, BUT without copy-pasting when the protocol's interface clearly can be made generic, like in the above.
As swift provides a way to declare generic protocols (using associatedtype keyword) it's impossible to declare a generic protocol property without another generic constraint. So the easiest way would be to declare resource service class generic - class SomeResourceService<Repository: GenericRepository>.
But this solution has a big downside - you need to constraint generics everywhere this service would be involved.
You can drop generic constraint from the service declaration by declaring local as a concrete generic type. But how to transit from generic protocol to the concrete generic class?
There's a way. You can define a wrapper generic class which conforms to GenericRepository. It does not really implements its methods but rather passes to an object (which is real GenericRepository) it wraps.
class AnyGenericRepository<ResourceType: Identifiable>: GenericRepository {
// any usage of GenericRepository must be a generic argument
init<Base: GenericRepository>(_ base: Base) where Base.ResourceType == ResourceType {
// we cannot store Base as a class property without putting it in generics list
// but we can store closures instead
indexGetter = { base.index() }
// and same for other methods or properties
// if GenericRepository contained a generic method it would be impossible to make
}
private let indexGetter: () -> [ResourceType] {
indexGetter()
}
// ... other GenericRepository methods
}
So now we have a concrete type which wraps real GenericRepository. You can adopt it in SomeResourceService without any alarm.
class SomeResourceService {
let local: AnyGenericRepository<SomeResource>
}

Swift: casting un-constrained generic type to generic type that confirms to Decodable

Situation
I have a two generic classes which will fetch data either from api and database, lets say APIDataSource<I, O> and DBDataSource<I, O> respectively
I will inject any of two class in view-model when creating it and view-model will use that class to fetch data it needed. I want view-model to work exactly same with both class. So I don't want different generic constraints for the classes
// sudo code
ViewModel(APIDataSource <InputModel, ResponseModel>(...))
// I want to change the datasource in future like
ViewModel(DBDataSource <InputModel, ResponseModel>(...))
To fetch data from api ResponseModel need to confirms to "Decodable" because I want to create that object from JSON. To fetch data from realm database it need to inherit from Object
Inside ViewModel I want to get response like
// sudo code
self.dataSource.request("param1", "param2")
If developer tries to fetch api data from database or vice-versa it will check for correct type and throws proper error.
Stripped out version of code for playground
Following is stripped out version of code which shows what I want to achieve or where I am stuck (casting un-constrained generic type to generic type that confirms to Decodable)
import Foundation
// Just to test functions below
class DummyModel: Decodable {
}
// Stripped out version of function which will convert json to object of type T
func decode<T:Decodable>(_ type: T.Type){
print(type)
}
// This doesn't give compilation error
// Ignore the inp
func testDecode<T:Decodable> (_ inp: T) {
decode(T.self)
}
// This gives compilation error
// Ignore the inp
func testDecode2<T>(_ inp: T){
if(T.self is Decodable){
// ??????????
// How can we cast T at runtime after checking T confirms to Decodable??
decode(T.self as! Decodable.Type)
}
}
testDecode(DummyModel())
Any help or explanation that this could not work would be appreciated. Thanks in advance :)
As #matt suggests, moving my various comments over to an answer in the form "your problem has no good solution and you need to redesign your problem."
What you're trying to do is at best fragile, and at worst impossible. Matt's approach is a good solution when you're trying to improve performance, but it breaks in surprising ways if it impacts behavior. For example:
protocol P {}
func doSomething<T>(x: T) -> String {
if x is P {
return "\(x) simple, but it's really P"
}
return "\(x) simple"
}
func doSomething<T: P>(x: T) -> String {
return "\(x) is P"
}
struct S: P {}
doSomething(x: S()) // S() is P
So that works just like we expect. But we can lose the type information this way:
func wrapper<T>(x: T) -> String {
return doSomething(x: x)
}
wrapper(x: S()) // S() simple, but it's really P!
So you can't solve this with generics.
Going back to your approach, which at least has the possibility of being robust, it's still not going to work. Swift's type system just doesn't have a way to express what you're trying to say. But I don't think you should be trying to say this anyway.
In the method that fetch data I will check type of generic type and if it confirms to "Decodable" protocol I will use it to fetch data from api else from database.
If fetching from the API vs the database represents different semantics (rather than just a performance improvement), this is very dangerous even if you could get it to work. Any part of the program can attach Decodable to any type. It can even be done in a separate module. Adding protocol conformance should never change the semantics (outwardly visible behaviors) of the program, only the performance or capabilities.
I have a generic class which will fetch data either from api or database
Perfect. If you already have a class, class inheritance makes a lot of sense here. I might build it like:
class Model {
required init(identifier: String) {}
}
class DatabaseModel {
required init(fromDatabaseWithIdentifier: String) {}
convenience init(identifier: String) { self.init(fromDatabaseWithIdentifier: identifier )}
}
class APIModel {
required init(fromAPIWithIdentifier: String) {}
convenience init(identifier: String) { self.init(fromAPIWithIdentifier: identifier )}
}
class SomeModel: DatabaseModel {
required init(fromDatabaseWithIdentifier identifier: String) {
super.init(fromDatabaseWithIdentifier: identifier)
}
}
Depending on your exact needs, you might rearrange this (and a protocol might also be workable here). But the key point is that the model knows how to fetch itself. That makes it easy to use Decodable inside the class (since it can easily use type(of: self) as the parameter).
Your needs may be different, and if you'll describe them a bit better maybe we'll come to a better solution. But it should not be based on whether something merely conforms to a protocol. In most cases that will be impossible, and if you get it working it will be fragile.
What you'd really like to do here is have two versions of testDecode, one for when T conforms to Decodable, the other for when it doesn't. You would thus overload the function testDecode so that the right one is called depending on the type of T.
Unfortunately, you can't do that, because you can't do a function overload that depends on the resolution of a generic type. But you can work around this by boxing the function inside a generic type, because you can extend the type conditionally.
Thus, just to show the architecture:
protocol P{}
struct Box<T> {
func f() {
print("it doesn't conform to P")
}
}
extension Box where T : P {
func f() {
print("it conforms to P")
}
}
struct S1:P {}
struct S2 {}
let b1 = Box<S1>()
b1.f() // "it conforms to P"
let b2 = Box<S2>()
b2.f() // "it doesn't conform to P"
This proves that the right version of f is being called, depending on whether the type that resolves the generic conforms to the protocol or not.

Extension Error Swift 3 JSON

I'm trying to migrate my app to Swift 3 but I have troubles.
The code section that struggles me is:
extension JSON: Swift.BooleanType {
//Optional bool
public var bool: Bool? {
get {
switch self.type {
case .bool:
return self.object.boolValue
default:
return nil
}
}
set {
if newValue != nil {
self.object = NSNumber(value: newValue! as Bool)
} else {
self.object = NSNull()
}
}
}
On first line is where xCode throws an error:
extension JSON: Swift.BooleanType {
The error says: Inheritance from non-protocol type 'BooleanType' (aka 'Bool')
Does anybody know what's happening there?
Simplest solution is here,
Bad : extension JSON: Swift.BooleanType {
Good : extension JSON: {
Reason : Admittedly, I am using this to modify SwiftyJSON which is a framework for processing JSON data. In doing some research it seems that they didn't allow BooleanType to allow for inheritance. The suggested means of dealing with this is simply to remove the type.
link is given : https://forums.developer.apple.com/thread/53405
Protocols are Swift's equivalent of Java interfaces. If you've never worked with interfaces before, they're classes absent of any concrete implementation. They exist to describe the skeleton of a class (the attribute and method names it should have) without actually implementing them so that other classes that inherit from the interface can flesh them out later. In Swift they're particularly useful for implementing the Delegate pattern.
Boolean is not a protocol. It is very much a living, breathing concrete Type with an existing implementation. To do what you want to do you either need to override the existing get/set method for Boolean type or create your own Boolean type as described in the official Apple Swift Blog.

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.