4

I am trying to implement a derived interface in a class. My interfaces and class are similar to the following. The Namespaces relate to different projects that hold these interfaces and the class:

Namespace ns1

    Public Interface IParent

        Function myFunction() As Double

    End Interface

End ns1

Namespace ns2

    Public Interface IDerived
        Inherits ns1.IParent

        Overloads / Shadows Function myFunction(ByRef myObject as Object) As Double

    End Interface

End ns2

Namespace ns3

    Public Class myClass
        Implements ns2.IDerived

        Public Function myFunction(ByRef obj as Object) As Double Implements ns2.IDerived.myFunction

        End Function

End ns3

In the derived interface, I am trying to overload the function in a way that when I implement the derived interface, I only have to implement the function as defined therein - as is done with the code above on "myClass". However, I am getting an error saying I have to also implement the function from the parent interface (with the empty argument list). The error exists regardless of my using Overloads or Shadows on the function in the derived interface - both cause the error.

Is there anyway to accomplish what I am trying to do - implement only the derived interface's function in my class - using interfaces? If there is not a way using interfaces, can anyone suggest an alternate way? We really need to use interfaces and are trying to avoid using classes. That said, abstract classes my allow us to do all we need to do with these.

I have read a lot of info on all the topics covered by this question as every concept is pretty basic and well covered in online help. But, I have not found anything that I recognize as a direct solution to my specific issue.

Thanks in advance for any help.

llc381
  • 101
  • 2
  • 10

2 Answers2

2

I don't believe that what you want to accomplish is possible the way you are trying... As I recall when you inherit an Interface any class that implements your derived Interface is actually being told that it must implement both Interfaces rather allowing the options you have in a full class.

So effectively what you have in myClass is:

Namespace ns3

    Public Class myClass
        Implements ns2.IDerived
        Implements ns1.IParent

        Public Function myFunction(ByRef obj as Object) As Double Implements ns2.IDerived.myFunction

        End Function

End ns3

So inheriting an interface is really just a way to enforce that a class implementing the derived interface must also implement the base interface.

Jay
  • 5,897
  • 1
  • 25
  • 28
  • I am too new to up vote your reply, but I believe you are correct. That is what the compiler seems to be leading me to anyway. I can implement both functions in myClass and only ever call the one I need. It just didn't make sense why overloading did not work. Thanks for the reply. – llc381 Jun 20 '13 at 22:31
  • 1
    I did a few more searches and although this is in c# I think it explains it a little better than I did. http://haacked.com/archive/2009/11/09/interface-inheritance-esoterica.aspx – Jay Jun 20 '13 at 22:42
  • Not the same issue: here the compiler complain is legitimate: the class claims it respects a contract that states that the class **MUST** have two overloads of *myFunction*, and this should be true in any language. What is strange is the fact VB.net does not support hiding whereas C# supports it allowing a redefinition in a sub interface to hide one above, avoiding the implementer the burden of implementing two methods if both have the same semantics. – Pragmateek Jun 20 '13 at 23:01
  • @Pragmateek, do I understand you correctly that if I were writing this in C#, my Shadows (Overloads in C#) would be legitimate and my implementation of the derived interface in the class would allow me to use only the derived (overloaded) method and not require implementation of the parent interface's function? – llc381 Jun 20 '13 at 23:08
  • @D.. I see why you posted the link, as it does state that any class implementing the derived interface has to honor the contract created by the interfaces inheritance tree. That was your original point. That is the kind of help I came across before posting. None of the examples directly address inheritance and overloading in derived interfaces. The (seemingly) unusual vb.net behavior of not honoring the Shadows (Overloads) declaration on the derived method is what threw me for a loop. Thanks for the link! – llc381 Jun 20 '13 at 23:19
  • @llc381: in C# the nearest equivalent of **Shadows** is **new**. But it will only allow you to hide if the two method declarations are strictly the same. So my example with two "*myFunction()*" would work. As for your original request, as said in my other comments, it is not legitimate, so it would fail with the same error in C#. – Pragmateek Jun 20 '13 at 23:19
  • @llc381: the point of the article is that interfaces are different beasts than classes: they do not exhibit the members of their parent. It's related to your issue but not the same because yours would also appear in an **abstract classes hierarchy**. – Pragmateek Jun 20 '13 at 23:26
2

I don't know if this is a typo but you have two distinct methods: one that takes no parameter, and another that takes an object, so the compiler requirement is legitimate.

If this is a typo and that you have only one method, say "myFunction()", then I fear VB.Net does not act like C# by simply hiding the base interface and allowing to only implement the derived one.

But you could easily fix this by forwarding:

Namespace ns1

    Public Interface IParent

        Function myFunction() As Double

    End Interface

End Namespace

Namespace ns2

    Public Interface IDerived
        Inherits ns1.IParent

        Function myFunction() As Double

    End Interface

End Namespace

Namespace ns3

    Public Class Class1
        Implements ns2.IDerived

        Public Function myFunction() As Double Implements ns2.IDerived.myFunction
            Return 42
        End Function

        Private Function myFunction1() As Double Implements ns1.IParent.myFunction
            Return myFunction()
        End Function
    End Class

End Namespace

Module Module1

    Sub Main()
        Dim cp As ns1.IParent = New ns3.Class1
        cp.myFunction()

        Dim cd As ns2.IDerived = New ns3.Class1
        cd.myFunction()
    End Sub

End Module

EDIT: So was not a typo, here is the standard (good/best practice?) fix:

Public Class Class1
    Implements ns2.IDerived

    Public Function myFunction(ByRef obj As Object) As Double Implements ns2.IDerived.myFunction

    End Function

    Public Function myFunction() As Double Implements ns1.IParent.myFunction
        Throw New NotImplementedException("'ns1.IParent.myFunction' has not been implemented because unicorns can't fly!")
    End Function
End Class
Pragmateek
  • 13,174
  • 9
  • 74
  • 108
  • No, not a typo. I am trying to overload the inherited method from parent in the derived; that is due to the different projects where the interfaces live, and the ultimate use of each project. In a nutshell, project ns1 is a generic project that project ns2 uses in a specific scenario. However, we have them separated due to ns1 also being used in other scenarios not related to ns2. Thanks for the reply. – llc381 Jun 20 '13 at 22:28
  • So what happens is completely expected: you can't just throw away a part of an interface because the code that uses the interface **expects a given contract** you MUST comply with. If you'll never implement this contract you can make it explicit to the user of the interface **dynamically** using the common "not implemented" pattern. I'll update my answer with a sample. :) – Pragmateek Jun 20 '13 at 22:46
  • Good point - we are familiar with NotImplementedException :). My hope was that interfaces were handled such that declaring the function as "Overloads" or "Shadows" in the derived interface would effectively hide the base interface function and allow me to use only the derived interface function in my class. I'll try that again when the unicorns come home ;). Until then, I'll just have to accept it as is. We will likely go with the explicit NotImplementedException - thank you for the reminder of the simple(st) solution! – llc381 Jun 20 '13 at 22:59
  • Ok, but keep in mind the fundamental reason why your expectations were wrong: imagine that you could hide as you wanted, what would happen if a caller wrote: `Dim cp As ns1.IParent = New ns3.Class1 cp.myFunction()`? Would it throw a VB.Net special exception? Would it call the other overload with *Nothing* as a parameter? – Pragmateek Jun 20 '13 at 23:14
  • Moreover imagine a less trivial case where the base method has different parameters like a string? If you can find a reasonable answer then your expectations are right and you should submit a feature request to the VB.Net team, otherwise you'll understand why you were expecting too much. :) – Pragmateek Jun 20 '13 at 23:14
  • Ahhhh, yes. We don't typically declare in that fashion - as a type / superclass that is of (=) a subclass type. I'm probably off on my terms here, given that I am using interface and class, but I get your point. In most cases for us, the "class" in my example is a webpage (.aspx) that will not be instantiated into an instance of the class (page). But, that doesn't change the fact that the webpage is indeed a class that can be extended. I will study on that more (when my brain is not mushed from a full work day). Excellent point! – llc381 Jun 20 '13 at 23:27
  • Marked as accepted answer due to additional information on NotImplementedException - that gave me the final piece of my question "how can I accomplish what I am trying to do using interfaces". – llc381 Jun 20 '13 at 23:38