Home > Back-end >  SWIFT iterating through structures - issue
SWIFT iterating through structures - issue

Time:07-29

Im trying to iterate thorough and array of structures using generics and I keep getting this error. Value of type [T] has no member 'printMessage'

My 2nd questions is - What message would print? The statement in the Foo protocol extension or the statement in the struct instance?

Not sure what the issue is.. and its driving me insane!

protocol Foo {

    func printMessage()
}


extension Foo {

    func printMessage() {
        print("Hello")
    }
    
}

struct test: Foo {

    func printMessage() {
        print("Goodbye")
    }
    
}



func MessagePrinter<T: Foo>(for message: [T]) {
    
    for message in [message] {
        message.printMessage()
    }

CodePudding user response:

For more clarity name the array in plural form and and the element in singular form.

And the square brackets in the for loop are wrong, the parameter is already an array

func messagePrinter<T: Foo>(for messages: [T]) {
    
    for message in messages {
        message.printMessage()
    } 
}

And please name functions always with starting lowercase letter.

The method in the protocol extension is called unless the method is implemented.


But consider that T is a single concrete type at runtime, you cannot call the method on a heterogenous Foo array like this

let messages : [Foo] = [Test()]
messagePrinter(for: messages)

You will get the error

Protocol 'Foo' as a type cannot conform to the protocol itself

To be able to call the method on an heterogenous array whose elements conform to Foo you have to declare

func messagePrinter(for messages: [Foo]) { ...

CodePudding user response:

You are wrapping an array in another array here:

func MessagePrinter<T: Foo>(for messages: [T]) {
    for message in [messages] {
        message.printMessage()
    }
}

(I've renamed your function argument from message to messages to make it clearer.)

When you write [messages] you end up with an array containing another array containing T, so the type is [[T]]. The single element message thus has type [T], and an array has no method printMessage.

What you want is this:

func MessagePrinter<T: Foo>(for messages: [T]) {
    for message in messages {
        message.printMessage()
    }
}

As for what's printed when you execute it: that depends on what elements you feed it. If the elements implement printMessage those methods are called (e.g. "Goodbye"). Otherwise the default implementation you have provided for the protocol is called ("Hello").

  • Related