Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between using or not using the 'where' clause with generics?

Tags:

generics

swift

What's the difference between these two methods of declaring a generics superclass with or without the 'where' clause?

func foo<T: SomeClass>(object: T) -> Array<T>

func foo<T>(object: T) -> Array<T> where T: SomeClass
like image 201
Mattia C. Avatar asked Oct 18 '17 12:10

Mattia C.


People also ask

Why would you use generics in Swift?

Swift Generics allows us to create a single function and class (or any other types) that can be used with different data types. This helps us to reuse our code.

What is the difference between any object and generics?

In simple terms, AnyObject is Swift's analogue to Objective-C's id. The first function, preserves the type of the input argument for us thanks to generics. If we pass in an Int, it returns an Int because the compiler can infer the return type.

What are generic constraints in C#?

The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.

What are generics How do you make a method or variable generics in Swift?

Generics allow you to declare a variable which, on execution, may be assigned to a set of types defined by us. In Swift, an array can hold data of any type. If we need an array of integers, strings, or floats, we can create one with the Swift standard library.


2 Answers

This is clearly stated in the Swift guide:

The requirements in a generic where clause specify that a type parameter inherits from a class or conforms to a protocol or protocol composition. Although the generic where clause provides syntactic sugar for expressing simple constraints on type parameters (for instance, <T: Comparable> is equivalent to <T> where T: Comparable and so on), you can use it to provide more complex constraints on type parameters and their associated types. For instance, you can constrain the associated types of type parameters to conform to protocols. For example, <S: Sequence> where S.Iterator.Element: Equatable specifies that S conforms to the Sequence protocol and that the associated type S.Iterator.Element conforms to the Equatable protocol. This constraint ensures that each element of the sequence is equatable.

Simply put, where lets you specify constraints about the associated types of a generic parameter, while in <> you can't do this.

like image 71
Sweeper Avatar answered Sep 18 '22 19:09

Sweeper


Questions like these always require some practical examples, even the simplest to get basic idea. Otherwise it often remains theoretical.

As referenced by Sweeper, that which is after where is called type constraint. Typically you specify one or more protocols which introduce conditions which must be met by passed object or a type. And as mentioned, it's only after where where you can specify associatedtype constraint of the generic type.

Consider the following example:

protocol MyProtocol {
    associatedtype AType

    func foo()
}

class MyClassInt : NSObject, MyProtocol {
    typealias AType = Int

    func foo() {
        print(type(of: self))
    }
}

class MyClassString : NSObject, MyProtocol {
    typealias AType = String

    func foo() {
        print("I'm not implemented")
    }
}

extension MyProtocol where Self.AType == Int {
    func test() {
        self.foo()
    }
}

Now check our things:

let str = MyClassString()
str.test() // Won't compile !! 

'MyClassString.AType' (aka 'String') is not convertible to 'Int'

This one compiles and runs:

let int = MyClassInt()
int.test()

In this example we have a protocol with the associatedtype specified. And there's also an extension which is only applied to our MyProtocol with particular associatedtype, in our case Int. That extension defines single method. As you can see, compiler won't let us to call that method with the associatedtype other than that specified by a constraint, even though MyClassString also implements that protocol.

like image 37
Hexfire Avatar answered Sep 19 '22 19:09

Hexfire