A range of basic classes in the foundation framework can be made by simply assigning a basic number to the value where the desired type is known take for example CGFloat:
let a: CGFloat = 42
instead of having to simply use an init like so:
let a = CGFloat(42)
My question is what is this called when a struct or a class implements this behaviour and how can it be implemented for your own classes.
I don't believe this is matter of CGFloat being a type alias and I cannot seem to find a suitable answer for this.
Your type would need to implement the IntegerLiteralConvertible protocol.
That protocol requires you to implement a constructor of the form:
init(integerLiteral value: Self.IntegerLiteralType) {}
Example:
struct MyCoolStruct {
let value: Int
}
extension MyCoolStruct : IntegerLiteralConvertible {
init(integerLiteral value: Int) {
self.value = value
}
}
let instance: MyCoolStruct = 3
instance.value
Swift 4/5:
IntegerLiteralConvertible has been renamed in ExpressibleByIntegerLiteral:
extension MyStruct: ExpressibleByIntegerLiteral {
init(integerLiteral value: IntegerLiteralType) {
self.value = value
}
}
Related
The below code, where one is for Struct, the other is for Class.
I'm wondering why we need init for class and not struct (although we can add one to it)? Is there any technical reason behind that an init is required in class, but more relax in struct?
struct StructTest {
private let value: Int
}
class ClassTest {
private let value: Int
init(value: Int) {
self.value = value
}
}
Structs still have an initializers. The only differences is that in some cases the compiler will synthesize a "default member-wise initalizer" for you.
In this case, it created one with the signititure private init(value: Int) (private because your struct has a private field)
How can I do a check object conforms to protocol 'Representable' in a similar situation?
protocol Representable {
associatedtype RepresentType
var representType: RepresentType { get set }
}
class A: UIView, Representable {
enum RepresentType: String {
case atype = "isa"
}
var representType: RepresentType = .atype
}
class B: UIView, Representable {
enum RepresentType {
case btype(value: String?)
}
var representType: RepresentType = .btype(value: nil)
}
let obj = A()
if let obj = obj as? Representable { <<<<<<<<<<<< error
obj.representType = A.RepresentType.atype
}
Error: Protocol 'Representable' can only be used as a generic constraint because it has Self or associated type requirements
if let obj = obj as? Representable
It is important that each class implements its enumeration of types of representation, but the class can be checked of conforms to protocol
I believe what you're asking for is not possible, because RepresentType remains unknown until a confirming class defines it.
Here are some related SO questions that deal with the same issue:
In Swift, how to cast to protocol with associated type?
why is this causing so much trouble? (protocols and typealiases on their associated types)
According to Apple's documentation Swift does not necessary require override of initializer. In a following code example Bar inherits initializer of Foo:
class Foo {
let value: Int
init(value: Int = 5) {
self.value = value
}
}
class Bar: Foo {
}
As soon as we add some generic into Foo such as class Foo<T> { Xcode provides us a error Initializer does not override a designated initializer from its superclass. Is there a documentation or swift evolution discussion that explains why it is happening?
Update. It seems that generic is not a major cause for override requirement. Here are an option how to define a class with generic that does not require override of designated initializer:
protocol FooProtocol {
associatedtype T
}
class Foo<U>: FooProtocol {
typealias T = U
let value: Int
init(value: Int, otherValue: T) {
self.value = value
self.otherValue = otherValue
}
}
class Bar: Foo<Int> {
}
However there is another interesting observation of behavior. Defining initializer like following cause override requirement:
init(value: Int = 5) {
self.value = value
}
The funny thing thing that adding one more parameter as following into such designated initializer cause this override requirement to disappear:
init(value: Int = 5, otherValue: T) {
self.value = value
}
Update 2. I can not find a logical explanation to this behavior, at this point I reported it as Compiler bug — https://bugs.swift.org/browse/SR-1375
I actually filled a bug report for inheriting from generic class:
It was back in November last year and didn't get an answer yet, so ¯_(ツ)_/¯
It's clearly a bug. Moreover, although the bug is elicited by subclassing a generic, its proximate cause is the default value. This compiles just fine:
class Foo<T> {
let value: Int
init(value: Int) {
self.value = value
}
}
class Bar: Foo<String> {
}
But this does not:
class Foo<T> {
let value: Int
init(value: Int = 5) {
self.value = value
}
}
class Bar: Foo<String> {
}
That sort of arbitrary distinction without a difference is a sure indication that this is a compiler bug.
If I want to add an extension to every object I can do the following:
extension AnyObject
{
func myFunc() { ... }
}
Is there something similar where I can add a function to every Enum? In other words, what is the base "class" for every enum?
First of all, note that you cannot do an extension to AnyObject as above, as AnyObject is a protected protocol (to which all classes implicitly conform) rather than a type. See e.g.
Is there a way to add an extension to AnyObject?
Now, you could, however, extend any specific type as you show above, e.g., extension Int { ... }. However enum is not a type; rather a "container" of ordered raw representable values. So a more valid comparison could be "If I want to add an extension to every class, by extension class ...", which is, naturally, trickier.
Now, all enumerations with a rawValue and an initializer by rawValue conforms to protocol RawRepresentable, so you could extend this protocol for specific types of raw values:
extension RawRepresentable where RawValue == Int {
var sqrt: Double {
return pow(Double(rawValue),(1/2))
}
}
And this extension property would be available to all enumerations that explicitly use the same raw value type, in this case, Int:
enum MyIntegerLiteralEnum : Int {
case One = 1
case Two
case Three
case Four
}
print(MyIntegerLiteralEnum.One.sqrt)
print(MyIntegerLiteralEnum.Two.sqrt)
print(MyIntegerLiteralEnum.Four.sqrt)
/* 1.0
1.4142135623731
2.0 */
As a disclaimer, note that this extension will be made available to all types that conforms to RawRepresentable with a rawValue of type Int, not only enum types. E.g.:
struct Foo : RawRepresentable {
typealias RawValue = Int
var bar : Int
var rawValue: RawValue {
get {
return bar
}
}
init(rawValue bar: Int) {
self.bar = bar
}
}
var a = Foo(rawValue: 16)
print(a.sqrt) // 4.0
I need to get some objects from REST API and map them to local objects using ObjectMapper.
These objects contain a number of enumerations. All of them are coming as integers and I want to map them to locally described enums.
To do that I have to describe standard transform function that is used by ObjectMapper.
enum Types: Int {
case Uno = 1
case Dos = 2
case Tres = 3
static var transform = TransformOf<Types,Int>(
fromJSON: {
$0 != nil
? Types(rawValue:$0!)
: nil
},
toJSON: { $0?.rawValue})
}
The problem is that I have a number of these enumerations and the function is totally same in all of them except that first argument in TransformOf<..> list is specific for each enum.
What I want to do is to create a common protocol with default implementation of that function, something like
protocol Transformable {
var transform: TransformOf<self.Type,Int> {
get {
return TransformOf<self.Type,Int>(
fromJSON: {
$0 != nil
? Types(rawValue:$0!)
: nil
},
toJSON: { $0?.rawValue})
}
}
}
...and then to apply the protocol with the implementation to all of the enumerations I have.
Obviously reference of self.Type is not working there and I just can't get how to generally refer to type of specific instance that will finally use the function? Probably I'm thinking wrong way of solving that problem.
I think what you're missing is the Self identifier. When implementing Generics, the Self keyword acts as a placeholder for the type that implements your protocol. (For more information)
In other words:
protocol Transformable {
var rawValue: Int { get }
init?(rawValue: Int)
func toJSON() -> Int
static func fromJSON(rawValue: Int) -> Self?
}
Each enum that conforms to the protocol Transformable will then have a static method that returns its own type.
Secondly, since this is Swift 2, you can implement a protocol extension:
extension Transformable {
func toJSON() -> Int {
return self.rawValue
}
static func fromJSON(rawValue: Int) -> Self? {
return Self(rawValue: rawValue)
}
}
Now all enums that conform to the protocol will convert themselves to and from Int:
enum Types: Int, Transformable {
case Uno = 1
case Dos = 2
case Tres = 3
//No extra implementation
}
enum OtherTypes: Int, Transformable {
case Cuatro = 4
case Cinco = 5
case Seis = 6
//No extra implementation
}
print(Types.fromJSON(1)!) //prints Uno
print(OtherTypes.fromJSON(4)!) //prints Cuatro
print(Types.fromJSON(4)!) /* throws an error, because the Types enum
does not recognise 4 as a raw value */