10

I've stumbled upon an issue, and I can not figure out how am I going to solve it.

Let's suppose we have a base class (that may comes from FrameworkA), with a property named subject:

public class MyClass {
    public var subject: String
}

And we have a protocol (that may comes from FrameworkB), with another property but with the same name:

public protocol MyProtocol {
    var subject: String { get }
}

Those two properties represent totally different things.

How can I create a class that inherits from MyClass and implements MyProtocol? And how can I use these properties?

public class SecondClass: MyClass, MyProtocol {
    var MyProcotol.name: String { // <==== Obviously not allowed
        return "something"
    }
    var MyClass.name: String { // <==== Obviously not allowed
        return "something else"
    }
}

I think that C# allows some kind of declaration like this, but I'm not 100% sure...

6
  • 3
    You need to name things accordingly. If they are different you need different names. Commented Apr 30, 2015 at 12:03
  • Yes, of course :) But, what if I can't do anything about it, for example, the base class and the protocol are part of some frameworks (even separate frameworks) ? Commented Apr 30, 2015 at 13:02
  • 1
    @ThomasKilian I disagree with you, it is a very good question, the solution isn't set the name of the things accordingly always, things like this can be happen and the language(compiler) must be have a solution Commented Apr 30, 2015 at 13:11
  • Ok, so to fix the problem you send a bug report to Apple and wait a few years. That's not helping. What helps is if anyone declaring a protocol uses sensible names, and then you name your methods accordingly. Commented Apr 30, 2015 at 14:00
  • Yep, framework developers should use sensible names. But app developers also should stop having single classes trying to achieve too many disparate (and in this case conflicting) purposes. Commented Apr 30, 2015 at 14:21

2 Answers 2

3

If you have control over this base class and/or the protocol, you can give the properties unique names and that solves the problem.

If you cannot do that, the question becomes whether SecondClass really has to fulfill these two conflicting responsibilities itself. Specifically, what is MyProtocol? Some delegate protocol? You could instead have SecondClass vend a separate object that conforms to that protocol, eliminating the conflicting dual roles.

Bottom line, rather than having a single object attempt serve two conflicting purposes, split the responsibilities into separate objects resolving any such conflict.

Sign up to request clarification or add additional context in comments.

Comments

1

Ok, for a moment let's look at the problem from the point of view of the code that does use these classes and let's ignore how they are implemented.

Fact 1

If secondClass : SecondClass extends MyClass then I expect to be able to write:

secondClass.subject

Fact 2

If secondClass conforms to MyProtocol then I expect to be able to write

secondClass.subject

If we create a different way for secondClass to expose MyClass.subject and MyProtocol.subject we are breaking the Object Oriented Paradigm.

Infact

  1. When you extend a class, you implicitly inherit the all non private properties and methods, you cannot (and this is a good thing) rename them.
  2. When you conform to a protocol you expose all the non optional declared properties and methods exactly as they are described in the protocol

If SecondClass renamed the 2 properties like in your pseudo-code, we would not be able to write something like this.

let list : [MyClass] = [MyClass(), SecondClass()]

for elm in list {
    println(elm.subject)
}

A possible (partial) solution

You should avoid the is-a approach in favor of the has-a.

class SecondClass {
    let myClass : MyClass
    let somethingElse : MyProtocol

    init(myClass : MyClass, somethingElse:MyProtocol) {
        self.myClass = myClass
        self.somethingElse = somethingElse
    }

    var myClassSubject : String { get { return myClass.subject } }
    var myProtocolSubject : String { get { return somethingElse.subject } }
}

Now since

  1. SecondClass is not a MyClass and
  2. SecondClass is not a MyProtocol

It has not the subject property removing any risk of confusion.

Hope this helps.

4 Comments

@Victor Sigler: thank you for the better formatting!
I like your answer, but I think Apple need to correct this in future releases of Swift, because the compiler must be know how to deal with this kind of situations.
The problem here is that we are dealing with a conceptual constraint related to OOP. I really don't how the language itself could be changed to manage this kind of scenario.
The original proposal for traits Traits: Composable Units of Behaviour describes tools for such conflict resolutions which include alias and exclusion of methods (see 3.5 Conflict Resolution). Might be interested to you ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.