-1

In swift5.x, I want to use a protocol named Animal with an associatedType 'T'.

class Shape {
    func transform() {
        print("Shape transofrm")
    }
}

protocol Animal {
    associatedtype T: Shape
    var tansformT: T { get set }
    func bark()
}

var a: any Animal

Rectangle and Circle implements the Shape protocol:

class Rectangle: Shape {
    override func transform() {
        print("Rectangle transofrm")
    }
}

class Circle: Shape {
    override func transform() {
        print("Circle transofrm")
    }
}

And there are two class implements Animal protocol:

class Dog : Animal {
    var tansformT: Rectangle = Rectangle()
    func bark() {

    }
}

class Cat: Animal {
    var tansformT = Circle()
    func bark() {
        print("Cat bark")
    }
}

I want to declare a variable ani, it can be Dog or Cat according the condition, so i try this:

var a = 10
var ani: Animal
if a == 10 {
    ani = Cat()
} else {
    ani = Dog()
}

then the compiler reports an error: Protocol 'Animal' can only be used as a generic constraint because it has Self or associated type requirements I have try my best for 3+ hours, I don't know how to solve it.

1 Answers1

0

Here I found an answer that can help you out. https://stackoverflow.com/a/59330536/17286292

Failed with error: Protocol 'Animal' can only be used as a generic constraint because it has Self or associated type requirements

var ani: Animal = Cat()

But change to opaque result type like this, it will work.

var ani: some Animal = Cat()

Doc: https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html

From doc:

    struct Square: Shape {
        var size: Int
        func draw() -> String {
            let line = String(repeating: "*", count: size)
            let result = Array<String>(repeating: line, count: size)
            return result.joined(separator: "\n")
        }
    }

    func makeTrapezoid() -> some Shape {
        let top = Triangle(size: 2)
        let middle = Square(size: 2)
        let bottom = FlippedShape(shape: top)
        let trapezoid = JoinedShape(
            top: top,
            bottom: JoinedShape(top: middle, bottom: bottom)
        )
        return trapezoid
    }
    let trapezoid = makeTrapezoid()
    print(trapezoid.draw())
    // *
    // **
    // **
    // **
    // **
    // *

The makeTrapezoid() function in this example declares its return type as some Shape; as a result, the function returns a value of some given type that conforms to the Shape protocol, without specifying any particular concrete type. Writing makeTrapezoid() this way lets it express the fundamental aspect of its public interface—the value it returns is a shape—without making the specific types that the shape is made from a part of its public interface.

Neklas
  • 504
  • 1
  • 9
  • thanks, @Nekias, your answer is awesome. Maybe I didn't express my scenario clearly, so I change the question. I want to set `ani` to a different object as some condition. If you know how to do this, please give me the help, I will select your answer. – jacob sheldon Sep 12 '22 at 12:11