Home > database >  How to check type of Swift object, produced by factory method?
How to check type of Swift object, produced by factory method?

Time:09-05

I have an array of TemplateASTNode objects:

enum TemplateASTNode {
    case blockNode(Block)
    case sectionNode(Section)
    case textNode(String)
    
    
    // Define structs instead of long tuples
    struct Block {
        let innerTemplateAST: TemplateAST
        let name: String
    }
    
    struct Section {
        let tag: SectionTag
        let expression: Expression
        let inverted: Bool
    }
    
    // Factory methods
    static func block(innerTemplateAST: TemplateAST, name: String) -> TemplateASTNode {
        return .blockNode(Block(innerTemplateAST: innerTemplateAST, name: name))
    }
    
    static func section(templateAST: TemplateAST, expression: Expression, inverted: Bool, openingToken: TemplateToken, innerTemplateString: String) -> TemplateASTNode {
        let tag = SectionTag(innerTemplateAST: templateAST, openingToken: openingToken, innerTemplateString: innerTemplateString)
        return .sectionNode(Section(tag: tag, expression: expression, inverted: inverted))
    }
    
    static func text(text: String) -> TemplateASTNode {
        return .textNode(text)
    }
}

Objects are constructed with different factory methods — section, text, block, but in debugger actual class is TemplateASTNode.

  1. How to check actual type of TemplateASTNode instance — Section, Text, Block?
  2. How exacly this mechanism works? Need a start point what to google.

Swift magic seems a bit confusing for me:

  1. we call factory method section()
  2. it calls case sectionNode — I suppose it's a pointer to Enum attribute/choice
  3. sectionNode holds a pointer to constructor Section which is a private structure inside TemplateASTNode

I expect a struct of type Section should be instantiated, but the generic TemplateASTNode one is produced. Why?

CodePudding user response:

Why TemplateASTNode is Created

So the functions are actually using a case of the enum, this case could be .textNode but that case requires a string, which you give it.

So essentially the TemplateASTNode is acting as a wrapper to centralise all these models into one place, and your actual Structs are being held within the enum cases

Therefor you get given back a TemplateASTNode, which in this case could either be a .textNode .blockNode or .sectionNode each containing their respective data.

How to distinguish between them

As we've just established, these are all cases therefore we can use something called a switch. To sum up what this does, it essentially allows you to give it an enum, then add logic depending on which case it is. So for you, you'd want something like this:

switch templateASTNode { // These should be the variable and not the class
    case .textNode(let text):
        // Perform logic for text node

    case .sectionNode(let section):
        // Perform logic for section node

    case .blockNode(let block):
        // Perform logic for block node
}
  • Related