Home > Net >  how to test protocol conformance for optional struct
how to test protocol conformance for optional struct

Time:11-19

Checking if the Struct conformed to protocol, but if the nested struct is optional it always returns false,

example:

protocol XYZ {

}

extension XYZ {
  func test() { 
     print("asdsfd") 
  } 
}

struct Test1: XYZ { 
  var test2: Test2 
  var test3: Test3?

  init(){
    self.test2 = Test2()
    self.test3 = Test3() 
  }
}

struct Test2: XYZ {

}

struct Test3: XYZ {

}

Now: if I want check if the struct is using protocol

let x = Test1()

below condition will be true because Test2 conformed to XYZ protocol

print(type(of: x.test2) is XYZ.Type)

below condition will be false because Optional<Test2> conformed to XYZ protocol should be true but it's return false because of optional

print(type(of: x.test3) is XYZ.Type)

how should I handle the optional in this case, I tried by unwrapping optional but it's not happening. any help is appreciated.

I tried to unwrap the optional but it's not happening. I am trying to find a way to compare the optional type conforms to protocol.

CodePudding user response:

See The Swift Programming Language: Protocols: Checking for Protocol Conformance, in which the is, as? and as! operators can check for conformance directly, without needing to extract the type(of:):

Checking for Protocol Conformance

You can use the is and as operators described in Type Casting to check for protocol conformance, and to cast to a specific protocol. Checking for and casting to a protocol follows exactly the same syntax as checking for and casting to a type:

  • The is operator returns true if an instance conforms to a protocol and returns false if it doesn’t.

  • The as? version of the downcast operator returns an optional value of the protocol’s type, and this value is nil if the instance doesn’t conform to that protocol.

  • The as! version of the downcast operator forces the downcast to the protocol type and triggers a runtime error if the downcast doesn’t succeed.

So, rather than:

print(type(of: x.test2) is XYZ.Type) // true
print(type(of: x.test3) is XYZ.Type) // false

You can avoid type(of:) and test the conformance directly (which handles optionals):

print(x.test2 is XYZ)                // true
print(x.test3 is XYZ)                // true

CodePudding user response:

When checking for protocol conformance don't use Protocol.Type

protocol XYZ {

}

extension XYZ {
  func test() {
     print("asdsfd")
  }
}

struct Test1: XYZ {
  var test2: Test2
  var test3: Test3?

  init(){
    self.test2 = Test2()
    self.test3 = Test3()
  }
}

struct Test2: XYZ {

}

struct Test3: XYZ {

}

let x = Test1()

// does Test1 conform to XYZ?
print(x is XYZ)

// Does x.test2 conform to the protocol?
print(x.test2 is XYZ)

// Does x.test3 conform to the protocol?
print(x.test3 is XYZ)

// The above prints true, we're seeing if it can be an XYZ, but if we test like you do
print(x.test3 is XYZ.Type)
// This is false, as you said in your example.

In real coding scenarios you're going to be using

if let example = x.test3 as? MyProtocol { ... }

I can't think of a common scenario I've run into where I've ever needed to compare against a Protocol.Type.

Also, in this example at least, all this testing is not needed because the compiler knows ahead of time. To make an example where it wouldn't:

let y: Any = x.test3

if let y = y as? XYZ {
    print("Test")
}

Here the compiler doesn't know that y conforms to the protocol, as its type is Any, but we can try and cast it - which we can see does work.

  • Related