In Object-Oriented Programming like C#, “Interfaces” play a vital role. An interface defines the “functional standard (contract)” that a class must implement.
Using interfaces allows for the separation of specific processing details (implementation) from the access point (definition), enabling the writing of flexible and maintainable code. This article explains how to define interfaces and implement them in classes, using a message-sending function as an example.
Basic Syntax of Interfaces
The interface keyword is used to define an interface. By convention, the name starts with “I” (e.g., ISample).
- Can define: Signatures (type and name) of methods, properties, events, and indexers.
- Cannot define: Actual processing (method body) or fields (variables). Note: While default implementations are possible in C# 8.0 and later, the basis is “definition only”.
Practical Code Example: Standardizing Message Sending
The following code defines an IMessageSender interface representing message-sending functionality and creates an SmsSender class that concretely implements it.
using System;
namespace MessagingSystem
{
class Program
{
static void Main()
{
// Handle the instance as an interface type variable.
// This allows usage without knowing the implementation of the concrete class (SmsSender).
IMessageSender sender = new SmsSender();
sender.Send("090-1234-5678", "Hello. Your verification code is 1234.");
sender.Send("080-9876-5432", "Reservation completed.");
Console.WriteLine($"Total sent today: {sender.SentCount}");
}
}
// 1. Definition of the Interface
// Defines only the specification of "what the class should do".
public interface IMessageSender
{
// Method definition (do not write accessibility modifiers like public)
void Send(string recipient, string message);
// Property definition (can specify get only, set only, or both)
int SentCount { get; }
}
// 2. Implementation of the Interface
// Write ": InterfaceName" after the class name.
public class SmsSender : IMessageSender
{
// Implementation of Property
// Although the interface only specifies 'get',
// the implementation adds 'private set' to allow internal value changes.
public int SentCount { get; private set; }
// Implementation of Method
// Methods defined in the interface must be implemented as public.
public void Send(string recipient, string message)
{
// Actual SMS sending process (substituted with console output here)
Console.WriteLine($"[SMS Send] To: {recipient}, Body: {message}");
// Increment send count
SentCount++;
}
}
}
Execution Result
[SMS Send] To: 090-1234-5678, Body: Hello. Your verification code is 1234.
[SMS Send] To: 080-9876-5432, Body: Reservation completed.
Total sent today: 2
Technical Points
1. Role as a Contract
When implementing an interface (class SmsSender : IMessageSender), that class must implement all members (methods and properties) defined in the interface. Failure to do so results in a compilation error. This creates a guarantee that “if a class has this interface, the Send method can definitely be called.”
2. Property Implementation and Accessibility
Even if a property is defined as { get; } on the interface side, it is possible to implement it as { get; set; } or { get; private set; } on the implementation class side. The interface indicates the “minimum requirement.” However, implemented members must always be public.
3. Leveraging Polymorphism
By typing the variable as the interface type (IMessageSender) as shown in the Main method, the calling code (the part calling the Send method) does not need to change even if the instance assigned is switched from SmsSender to EmailSender or LineSender. This is one of the greatest benefits of using interfaces.
Summary
Defining interfaces allows for the separation of application “specifications” from “implementations.” While it may seem like extra work initially, it is an essential technique in class design when considering testability and future functional extensions (such as adding sending methods other than SMS).
