I'm building a decent sized application in ASP.NET/VB.NET with various objects... I've never used interfaces before, and a fellow programmer balked when I mentioned this to him. Can anyone give me a quick overview on how they're used, what they're used for, and why I would use them? Maybe I don't need to use them for this project, but if they would help, I surely would love to try.
Thanks so much!
Once you "get" interfaces, OOP really falls into place. To put it simply, an interface defines a set of public method signatures, you create a class which implements those methods. This allows you generalize functions for any class which implements a particular interface (i.e. classes which have the same methods), even if those classes don't necessarily descend from one another.
Module Module1
Interface ILifeform
ReadOnly Property Name() As String
Sub Speak()
Sub Eat()
End Interface
Class Dog
Implements ILifeform
Public ReadOnly Property Name() As String Implements ILifeform.Name
Get
Return "Doggy!"
End Get
End Property
Public Sub Speak() Implements ILifeform.Speak
Console.WriteLine("Woof!")
End Sub
Public Sub Eat() Implements ILifeform.Eat
Console.WriteLine("Yum, doggy biscuits!")
End Sub
End Class
Class Ninja
Implements ILifeform
Public ReadOnly Property Name() As String Implements ILifeform.Name
Get
Return "Ninja!!"
End Get
End Property
Public Sub Speak() Implements ILifeform.Speak
Console.WriteLine("Ninjas are silent, deadly killers")
End Sub
Public Sub Eat() Implements ILifeform.Eat
Console.WriteLine("Ninjas don't eat, they wail on guitars and kick ass")
End Sub
End Class
Class Monkey
Implements ILifeform
Public ReadOnly Property Name() As String Implements ILifeform.Name
Get
Return "Monkey!!!"
End Get
End Property
Public Sub Speak() Implements ILifeform.Speak
Console.WriteLine("Ook ook")
End Sub
Public Sub Eat() Implements ILifeform.Eat
Console.WriteLine("Bananas!")
End Sub
End Class
Sub Main()
Dim lifeforms As ILifeform() = New ILifeform() {New Dog(), New Ninja(), New Monkey()}
For Each x As ILifeform In lifeforms
HandleLifeform(x)
Next
Console.ReadKey(True)
End Sub
Sub HandleLifeform(ByVal x As ILifeform)
Console.WriteLine("Handling lifeform '{0}'", x.Name)
x.Speak()
x.Eat()
Console.WriteLine()
End Sub
End Module
None of the classes above descend from one another, but my HandleLifeform method is generalized to operate on all of them -- or really any class which implements the ILifeform interface.
Since the basics have already been covered, lets move on to practical examples.
Say I'm going to have a Dictionary that stores String keys and Person objects and I'm going to pass this dictionary (actually, the reference to it) to some methods I have.
Now, my receiving method would look something like
Imports System.Collections.Generic
Public Sub DoSomething(ByVal myDict As Dictionary(Of String, Person))
' Do something with myDict here
End Sub
right?
But what if someone invents some new high performance dictionary class? I have to turn around and change every reference to Dictionary to FastDictionary!
However, if I had coded to the interface in the first place, I wouldn't have this problem:
Imports System.Collections.Generic
Public Sub DoSomething(ByVal myDict As IDictionary(Of String, Person))
' Do something with myDict here
End Sub
Now it takes any dictionary!
Interfaces basically allow you to define a type's contract without specifying its implementation.
The idea is that if you know that a given type implements a certain interface it is guaranteeing that certain methods and properties are members of that type.
So any type that implements the following interface:
Interface ISpinnable
Sub Spin()
End Interface
Would have to implement the Spin method. But the caller of this type that implements ISpinnable does not care about how it is implemented, it just cares that the method is there. Here is a type that implements ISpinnable:
Class Top Implements ISpinnable
Sub Spin()
' do spinning stuff
End Sub
End Class
The benefit to this is that you can create method arguments of type ISpinner and allow the caller of these methods to pass any type to you as long as it implements the interface. Your method is no longer tightly coupled to the concrete type that the caller is using.
An interface is a contract without an implementation. It allows you to define what a type will look like without indicating what the implementation of that type is.
This allows you to have various implementations of an interface, which would suit your particular needs.
A good example is the IComparer(Of T) interface. You can have one implementation that will compare two items based on which is greater, and then another which will return a value based on which is lesser.
Then, you could pass one or the other to the static Sort method on the Array class to sort your items in ascending, or descending order, respectively.
One of the things interfaces can be useful is browsing through the array of objects of different types but which share the same interface.
Can't say for VB, but in C# you can use the handy "is" operator to determine if object's type implements the given interface and it's safe to access methods of that interface by casting. Sorry for C#, but i'll try to put some comments in =))
//we declare 3 different interfaces each requiring to implement one method
interface IProgrammer
{
void WriteCode();
}
interface ITester
{
void FindBugs();
}
interface IWorker
{
void StartShift();
}
// each programmer will be able to start his shift and write code
class Programmer : IWorker, IProgrammer
{
public void StartShift()
{
// ...
}
public void WriteCode()
{
// ...
}
}
// each tester will be able to start his shift and find bugs
class Tester : IWorker, ITester
{
public void StartShift()
{
// ...
}
public void FindBugs()
{
// ...
}
}
//then in code you can rely on objects implementing the interface to
// be able to do tasks interface requires to do
static void Main()
{
IWorker[] workers = new IWorker[3];
workers[0] = new Programmer();
workers[1] = new Tester();
workers[2] = new Tester();
// now we can browse through array of different workers because they all share
// the IWorker interface
foreach(IWorker worker in workers)
{
// All IWorkers can StartShift so we access its methods without casts
worker.StartShift();
if(worker is IProgrammer)
{
// Since that worker also implements IProgrammer
// we cast worker as IProgrammer and access IProgrammer method(s)
(worker as IProgrammer).WriteCode();
}
if(worker is ITester)
{
// Same,
// we cast worker as ITester and access ITester method(s)
// handy! =)
(worker as ITester).FindBugs();
}
}
A classic example is the Data Layer where you use it to support multiple database format. This was actually very useful before ORMappers came into the picture in mainstream programming.
Your interface just tells what type of method and properties your object has, the object itself then has to implement these methods.
IMyDatabase myDb;
switch case myDbFormat {
case "mysql":
myDb = new MyDbMySql();
break;
case "mssql" :
myDb = new MyDbMsSql();
break;
}
myDb.SaveToDatabase(some data)
Ofcourse the myDb classes have to implement the ImyDatabase Interface. I assume you can see how useful this is :).
Related
Hi I need to create a class for return the data in WCF service. I followed the web at 5 simple steps to create your first RESTful service. However I get the error for . I searched the web and add the System.Runtime.Serialization.DataContractSerializer, Would someone tell me what should do. I am using VS2015 as the tool to build it. Thanks.
Imports System.Runtime.Serialization
Imports System.Collections.Generic
Imports System.Runtime.Serialization.DataContractSerializer
<DataContract>
Public Class Locations
<DataMember>
Public Property LocationName As String
<DataMember>
Public Property LocationID As Integer
End Class
Could you please share the error details with me?
As you know, we usually use the datacontract to transmit the complex data type which could be recognized by the client-side and server-side. so that the data could be serialized and transmitted normally between different platforms.
For the restful web service in WCF, we need to use the Webhttpbinding build the data channel and add the Webhttpbehavior to the service endpoint.
I have made a demo, wish it is useful to you.
Server-side.
Imports System.Runtime.Serialization
Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports System.ServiceModel.Web
Module Module1
Sub Main()
Dim uri As New Uri("http://localhost:900")
Dim binding As New WebHttpBinding()
binding.CrossDomainScriptAccessEnabled = True
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None
Using sh As New ServiceHost(GetType(MyService), uri)
Dim se As ServiceEndpoint = sh.AddServiceEndpoint(GetType(IService), binding, uri)
se.EndpointBehaviors.Add(New WebHttpBehavior())
sh.Open()
Console.WriteLine("Service is ready")
Console.ReadLine()
sh.Close()
End Using
End Sub
<ServiceContract([Namespace]:="mydomain")>
Public Interface IService
<OperationContract>
<WebGet(ResponseFormat:=WebMessageFormat.Json)>
Function SayHello() As List(Of Product)
End Interface
Public Class MyService
Implements IService
Public Function SayHello() As List(Of Product) Implements IService.SayHello
Dim result = New List(Of Product)() From {
New Product With {
.Id = 1,
.Name = "Apple"
},
New Product With {
.Id = 2,
.Name = "Pear"
}
}
Return result
End Function
End Class
<DataContract([Namespace]:="mydomain")>
Public Class Product
<DataMember>
Public Property Id() As Integer
<DataMember>
Public Property Name() As String
End Class
End Module
Client.
$(function(){
$.ajax({
type:"GET",
url:"http://10.157.18.188:900/sayhello",
dataType:"jsonp",
success:function(d){
$.each(d,function(i,o){
console.log(o.Id);
console.log(o.Name);
})
}
})
})
Result.
Here is an official sample
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-a-basic-wcf-web-http-service
The following class is used in an ASP.NET application to read currencies from a database result set and add them up (e.g. show totals in US Dollars plus show totals in GB Pounds). It works in the following manner:
Read currency ID value
If currency ID exists already, increase the total for that currency
If currency ID does not exist, add it to the list with its value
Next
It works well using the CurrencyID property as the differentiator between each unique currency. However, it has now become apparent that IsoCurrencySymbol is also unique for each currency by default, and so CurrencyID is not actually needed.
So... I was wondering if it would be possible to inherit from this class and remove any reference to CurrencyID, therefore making the CompareTo method use IsoCurrencySymbol instead.
The trick is to leave the existing class as it is used extensively, but introduce a modified version without CurrencyID being needed. Is this possible to do please?
<Serializable()> _
Public Class CurrencyCounter
<Serializable()> _
Private Class CurrencyType
Implements IComparable
Public IsoCurrencySymbol As String
Public CurrencySymbol As String
Public CurrencyID As Int16
Public Amount As Decimal
Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo
If Not TypeOf (obj) Is CurrencyType Then
Throw New ArgumentException("Object is not a currency type")
Else
Dim c2 As CurrencyType = CType(obj, CurrencyType)
Return Me.CurrencyID.CompareTo(c2.CurrencyID)
End If
End Function
End Class
Private _Currencies As List(Of CurrencyType)
Public Sub New()
_Currencies = New List(Of CurrencyType)
End Sub
Private Sub AddStructToList(CurrencyID As Integer, IsoCurrencySymbol As String, CurrencySymbol As String, Amount As Decimal)
If IsoCurrencySymbol <> String.Empty AndAlso Amount > 0 Then
Dim s As New CurrencyType
s.CurrencyID = CurrencyID
s.IsoCurrencySymbol = IsoCurrencySymbol
s.CurrencySymbol = CurrencySymbol
s.Amount = Amount
_Currencies.Add(s)
End If
End Sub
Public Sub Add(CurrencyID As Integer, IsoCurrencySymbol As String, CurrencySymbol As String, Amount As Decimal)
Dim ct As CurrencyType = _Currencies.Find(Function(obj) obj.CurrencyID = CurrencyID)
If ct IsNot Nothing Then
ct.Amount += Amount
Else
AddStructToList(CurrencyID, IsoCurrencySymbol, CurrencySymbol, Amount)
End If
End Sub
Public Sub Clear()
_Currencies.Clear()
End Sub
Public Function Count() As Integer
Return _Currencies.Count
End Function
Public Function RenderTotals() As String
' ...
End Function
End Class
No, you cannot do that. The whole point of inheritance it to ensure that all derived classes, if nothing else, at least share the same public interface as their base class. If you are removing a property, then it doesn't share the same interface and is therefore incompatible and not a candidate for inheritance.
If you can't say that the derived class is a type of the base class, then you can't use inheritance. For instance, I can say that an automobile is a type of vehicle, therefore, if I had an automobile class, I could have it inherit from a vehicle class. I can't however say that an insect is a type of vehicle. Therefore, even if they share most things in common, I can't have an insect class inherit from a vehicle class.
The reason for this limitation is because inheritance allows you to treat an object as if it were the base type (via type casting). For instance:
Public Sub AddPassengerToVehicle(v As Vehicle)
v.Passengers.Add(New Passenger())
End Sub
' ...
Dim auto As New Automobile()
Dim bug As New Insect()
AddPassengerToVehicle(auto) ' Works because an automobile is a type vehicle (inherits from vehicle)
AddPassengerToVehicle(bug) ' Can't possibly work (nor should it)
So, if you are in a situation where you need to have a derived class that removes/hides one of the members of its base class, you are headed in the wrong direction. In a case like that, you would need to create a whole new class which just happens to have a very similar interface, but has no direct relationship with the first class, for instance:
Public Class Vehicle
Public Property Passengers As List(Of Passenger)
Public Property MaxSpeed As Integer
Public Function SpeedIsTooFast(speed) As Boolean
Return (speed > MaxSpeed)
End Function
End Class
Public Class Insect
Public Property MaxSpeed As Integer
Public Function SpeedIsTooFast(speed) As Boolean
Return (speed > MaxSpeed)
End Function
End Class
If you want to share functionality, such as the logic in the SpeedIsTooFast method in the above example, then there are a couple different ways to do that. This first would be to make wrapper methods which simply make calls to the other class, for instance:
Public Class Insect
Private _vehicle As New Vehicle()
Public Property MaxSpeed() As Integer
Get
Return _vehicle.MaxSpeed
End Get
Set(value As Integer)
_vehicle.MaxSpeed = value
End Set
End Property
Public Function SpeedIsTooFast(speed) As Boolean
Return _vehicle.SpeedIsTooFast(speed)
End Function
End Class
If you do it this way, it would be best to have both classes implement the same common interface so that you can use them interchangeably when necessary, for instance:
Public Interface ISelfPoweredMovingThing
Property MaxSpeed As Integer
Function SpeedIsTooFast(speed As Integer) As Boolean
End Interface
Another option would be to break out the common functionality into a third class and then use that class as the base for the other two, for instance:
Public Class SelfPoweredMovingThing
Public Property MaxSpeed As Integer
Public Function SpeedIsTooFast(speed) As Boolean
Return (speed > MaxSpeed)
End Function
End Class
Public Class Vehicle
Inherits SelfPoweredMovingThing
Public Property Passengers As List(Of Passenger)
End Class
Public Class Insect
Inherits SelfPoweredMovingThing
' Anything else specific only to insects...
End Class
We are developing a webservice for a client. We are not supose to throw SoapExceptions, so instead, we catch every exception server side, and return a custom Exception class.
Public Class Order
...
End Class
Public Class MyException
...
End Class
And then in my webservice a function (webmethod):
Public Function GetOrder(ByVal id As Integer) As Object
Try
...
Return New Order()
Catch ex As Exception
Return New MyException(ex.Message)
End Try
End Function
The problem now is, that since my webmethod is returning the type [Object]. The wdsl that is generated does not contain the order, or the exception.
I can change the [Object] to [Order] Or [MyException], but only one of them is generated in the wsdl.
So does anybody have an idea of how i should handle this? I want both the MyException type and the Order type in my wsdl, but i just cant get it working.
Thank you all.
If your definition of MyException
Public Class MyException
inherits System.Exception
...
End Class
then you shouldn't need to return the Custom Exception just throw it.
then you can define
Public Function GetOrder(ByVal id As Integer) As Order
Try
...
Return New Order()
Catch ex As Exception
Throw New MyException(ex.Message)
End Try
End Function
As I recall (and it's been a while) trying to return multiple objects from a web method can prove to be extremely troublesome
If you really want to return multiple objects, then maybe you should create a "wrapper" object, e.g something like this:
'please note: I don't normally use VB.NET, so there might be some errors
Public Class OrderResponse
Public Property Order() As Order
Get
Return m_Order
End Get
Set
m_Order = Value
End Set
End Property
Private m_Order As Order
Public Property Exception() As MyException
Get
Return m_Exception
End Get
Set
m_Exception = Value
End Set
End Property
Private m_Exception As MyException
End Class
Then change your method to return an instance of that class, with either the property Order or Exception set to the respective value:
Public Function GetOrder(ByVal id As Integer) As OrderResponse
...
End Function
I'm not sure if this is possible but I would like to associate a class name reference to a shared member method / property / variable. Consider:
Public Class UserParameters
Public Shared Reference As Object
Public Shared Function GetReference() As Object
Return Reference
End Function
End Class
In another part of the program I would like to simply call UserParameters and have it return Reference either by aliasing GetReference or the variable directly.
I am trying to emulate the Application, Request, or Session variable:
Session(0) = Session.Item(0)
Any suggestions would be greatly appreciated.
You can't return an instance member from a static method directly (the static method can't access instance members because it isn't instantiated with the rest of the class, only one copy of a static method exists).
If you need to setup a class in such a way that you can return an instance from a static method you would need to do something similar to the following:
Public Class SampleClass
Private Sub New()
'Do something here
End Sub
Public Shared Function GetSample() As SampleClass
Dim SampleClass As SampleClass
SampleClass = New SampleClass
SampleClass.Sample = "Test"
Return SampleClass
End Function
Private _SampleString As String
Public Property Sample As String
Get
Return _SampleString
End Get
Private Set(ByVal value As String)
_SampleString = value
End Set
End Property
End Class
Public Class SampleClass2
Public Sub New()
'Here you can access the sample class in the manner you expect
Dim Sample As SampleClass = SampleClass.GetSample
'This would output "Test"
Debug.Fail(Sample.Sample)
End Sub
End Class
This method is used in various places in the CLR. Such as the System.Net.WebRequest class. where it is instantiated in this manner in usage:
' Create a request for the URL.
Dim request As WebRequest = WebRequest.Create("http://www.contoso.com/default.html")
or can the class be implementing an abstract class also?
To mock a type, it must either be an interface (this is also called being pure virtual) or have virtual members (abstract members are also virtual).
By this definition, you can mock everything which is virtual.
Essentially, dynamic mocks don't do anything you couldn't do by hand.
Let's say you are programming against an interface such as this one:
public interface IMyInterface
{
string Foo(string s);
}
You could manually create a test-specific implementation of IMyInterface that ignores the input parameter and always returns the same output:
public class MyClass : IMyInterface
{
public string Foo(string s)
{
return "Bar";
}
}
However, that becomes repetitive really fast if you want to test how the consumer responds to different return values, so instead of coding up your Test Doubles by hand, you can have a framework dynamically create them for you.
Imagine that dynamic mocks really write code similar to the MyClass implementation above (they don't actually write the code, they dynamically emit the types, but it's an accurate enough analogy).
Here's how you could define the same behavior as MyClass with Moq:
var mock = new Mock<IMyInterface>();
mock.Setup(x => x.Foo(It.IsAny<string>())).Returns("Bar");
In both cases, the construcor of the created class will be called when the object is created. As an interface has no constructor, this will normally be the default constructor (of MyClass and the dynamically emitted class, respectively).
You can do the same with concrete types such as this one:
public class MyBase
{
public virtual string Ploeh()
{
return "Fnaah";
}
}
By hand, you would be able to derive from MyBase and override the Ploeh method because it's virtual:
public class TestSpecificChild : MyBase
{
public override string Ploeh()
{
return "Ndøh";
}
}
A dynamic mock library can do the same, and the same is true for abstract methods.
However, you can't write code that overrides a non-virtual or internal member, and neither can dynamic mocks. They can only do what you can do by hand.
Caveat: The above description is true for most dynamic mocks with the exception of TypeMock, which is different and... scary.
From Stephen Walther's blog:
You can use Moq to create mocks from both interfaces and existing classes. There are some requirements on the classes. The class can’t be sealed. Furthermore, the method being mocked must be marked as virtual. You cannot mock static methods (use the adaptor pattern to mock a static method).