Pangu
Pangu

Reputation: 3819

How to make different classes conform to the same protocol with different functionality?

I apologize beforehand if title is unclear, but I like to know how this is possible with some code snippets first:

ClassOne:

@objc protocol FetchProtocol
{
    var someVar: Bool
    {
        get set
    }

    var someUIView: FetchProtocol
    {
        get set
    }

    func someFuncOne()
}

class ClassOne: UIViewController, FetchProtocol
{
    ...

    @IBOutlet var someUIView: FetchProtocol!

    ....

}

ClassTwo:

@objc protocol FetchProtocol
{
    var someVar: Bool
    {
        get set
    }

    var someTableView: FetchProtocol
    {
        get set
    }

    var someUIView: FetchProtocol
    {
        get set
    }

    func someFuncOne()
    func someFuncTwo()
}

class ClassTwo: UIViewController, FetchProtocol
{
    ...

    @IBOutlet var someTableView: FetchProtocol!
    @IBOutlet var someUIView: FetchProtocol!

    ....

}

Both ClassOne and ClassTwo conform to the same FetchProtocol and both classes use the same someVar as well as someFuncOne, but ClassTwo also uses someTableView and someFuncTwo unique to only ClassTwo.

How can I use the same protocol between both classes, but the other class has "additional" different skeletal implementation?

For example, something like the following:

if let vc = currentVC as? FetchProtocol
{
    if vc.someVar == true
    {
        // Check if vc is of class type ClassOne, call someFuncOne

        // Otherwise if vc is of class type ClassTwo, call someFuncOne and someFuncTwo

    }
}

Is something like the above possible using protocols and if so, how to properly implement it, or is there another alternative?

Upvotes: 0

Views: 614

Answers (2)

Alexander
Alexander

Reputation: 63137

Your problem is quite abstract, and pretty hard to follow, but this does what you're asking for. That being said, I suspect there's no need for you to be using protocols here at all.

protocol P1 {
    var someVar1: String { get }

    func func1();
}

protocol P2: P1 {
    var someVar2: String { get }
    func func2();
}


class C1: P1 {
    var someVar1 = "String 1 in C1"

    func func1() {
        print(someVar1)
    }
}

class C2: P2 {
    var someVar1 = "String 1 in C2"
    var someVar2 = "String 2 in C2"

    func func1() {
        print(someVar1)
    }

    func func2() {
        print(someVar2)
    }
}


func foo(with object: P1) {
    object.func1()

    if let object = object as? P2 {
        object.func2()
    }
}

print("Test case 1:")
foo(with: C1())
print("Test case 1:\n")
foo(with: C2())

Upvotes: 1

Sweeper
Sweeper

Reputation: 270780

Your code doesn't compile and I think you're overcomplicating things and use protocols for the sake of using them.. There is no need to use any protocols at all if all you want to do is this:

if let vc = currentVC as? FetchProtocol
{
    if vc.someVar == true
    {
        // Check if vc is of class type ClassOne, call someFuncOne

        // Otherwise if vc is of class type ClassTwo, call someFuncOne and someFuncTwo

    }
}

Why not delete all protocols and just do:

if currentVC.someVar {
    if let class1 = currentVC as? ClassOne {
        class1.someFuncOne()
    } else if let class2 = currentVC as? ClassTwo {
        class2.someFuncOne()
        class2.someFuncTwo()
    }
}

You don't really need protocols here because whether protocols exist or not, you still have to check whether currentVC is ClassOne or ClassTwo.

Protocols act like "black boxes". Consider this method:

func foo(fetchObj: FetchProtocol) {
    fetchObj.someFuncOne()
}

foo doesn't care about what fetchObj really is. It just says "I don't care what you are, just do someFuncOne!"

What you're trying to do here is completely the opposite: "I do care what you are. If you're ClassOne, do this. If you're ClassTwo, do that."

Upvotes: 1

Related Questions