C
C#9mo ago
Falco

Practicing OOP in c#, is this logical implementation of an Interface?

c#
public interface IMembershipManager
{
void RegisterMembership(Person person);
void CancelMembership(Person person);
bool CheckMembership(Person person);
}

public class MembershipManager : IMembershipManager
{
public void RegisterMembership(Person person) {
person.Membership = true;
}
public void CancelMembership(Person person) {
person.Membership = false;
}

public bool CheckMembership(Person person) {
return person.Membership;
}
}

public class Person
{
public Person(string firstname, string lastname, bool membership)
{
FirstName = firstname;
LastName = lastname;
Membership = false;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Membership { get; set; }
}

public class Program{
public static void Main()
{
Person person = new Person("John", "John", false);
Console.WriteLine(person.FirstName);
Console.WriteLine(person.LastName);
Console.WriteLine(person.Membership);

IMembershipManager membershipManager = new MembershipManager();
membershipManager.RegisterMembership(person);
Console.WriteLine(person.FirstName);
Console.WriteLine(person.LastName);
Console.WriteLine(person.Membership);
}
}
c#
public interface IMembershipManager
{
void RegisterMembership(Person person);
void CancelMembership(Person person);
bool CheckMembership(Person person);
}

public class MembershipManager : IMembershipManager
{
public void RegisterMembership(Person person) {
person.Membership = true;
}
public void CancelMembership(Person person) {
person.Membership = false;
}

public bool CheckMembership(Person person) {
return person.Membership;
}
}

public class Person
{
public Person(string firstname, string lastname, bool membership)
{
FirstName = firstname;
LastName = lastname;
Membership = false;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Membership { get; set; }
}

public class Program{
public static void Main()
{
Person person = new Person("John", "John", false);
Console.WriteLine(person.FirstName);
Console.WriteLine(person.LastName);
Console.WriteLine(person.Membership);

IMembershipManager membershipManager = new MembershipManager();
membershipManager.RegisterMembership(person);
Console.WriteLine(person.FirstName);
Console.WriteLine(person.LastName);
Console.WriteLine(person.Membership);
}
}
39 Replies
Pobiega
Pobiega9mo ago
Yes and no. your MembershipManager doesn't actually do any meaningful work, it just manipulates a value on the Person model itself, which is already publicly mutable. But if the methods on that manager did something more interesting, like talk to a database, or emit messages to a broker or something, then you might have a more appropriate case for this structure
Falco
FalcoOP9mo ago
Yes in a real world scenario I would write to the database instead of just person.Membership = true;. Still not sure why I wouldn't use an abstract class for this?
Pobiega
Pobiega9mo ago
I don't follow, what would be abstract here?
Falco
FalcoOP9mo ago
I feel like I'm not yet fully understanding why I should use an interface here and not just something easier I mean what is the useful thing about an interface here
Pobiega
Pobiega9mo ago
Nothing at all its entirely dead weight
Falco
FalcoOP9mo ago
What would be a case where I definitely should use an interface?
Angius
Angius9mo ago
Two classes that share the same functionality
Pobiega
Pobiega9mo ago
Interfaces are useful in two capacities: guiding an implementation (oh I must have this method to fulfill the interface...) and providing an abstraction over multiple implementations lets say I have a IOutputHandler interface we might have a ConsoleOutputHandler and a FileOutputHandler or maybe even a DatabaseOutputHandler as long as they all implement the same interface, the rest of your codebase doesnt need to care about where the data actually ends up, or how its written there you just know that IOutputHandler has a Write(Guid id, string data) method
Falco
FalcoOP9mo ago
Is this what you mean
c#
using System;

public interface IOutputHandler
{
void Write(Guid id, string data);
}

public class ConsoleOutputHandler : IOutputHandler
{
public void Write(Guid id, string data)
{
Console.WriteLine($"Console: {id} - {data}");
}
}

public class FileOutputHandler : IOutputHandler
{
public void Write(Guid id, string data)
{
// Write to a file implementation
Console.WriteLine($"File: {id} - {data}");
}
}

public class DatabaseOutputHandler : IOutputHandler
{
public void Write(Guid id, string data)
{
// Write to a database implementation
Console.WriteLine($"Database: {id} - {data}");
}
}`
c#
using System;

public interface IOutputHandler
{
void Write(Guid id, string data);
}

public class ConsoleOutputHandler : IOutputHandler
{
public void Write(Guid id, string data)
{
Console.WriteLine($"Console: {id} - {data}");
}
}

public class FileOutputHandler : IOutputHandler
{
public void Write(Guid id, string data)
{
// Write to a file implementation
Console.WriteLine($"File: {id} - {data}");
}
}

public class DatabaseOutputHandler : IOutputHandler
{
public void Write(Guid id, string data)
{
// Write to a database implementation
Console.WriteLine($"Database: {id} - {data}");
}
}`
Pobiega
Pobiega9mo ago
yeah
Falco
FalcoOP9mo ago
Okay so I'm using the same function over multiple classes And that's not what I'm doing
Pobiega
Pobiega9mo ago
so in this case, you can have another method take a IOutputHandler outputHandler as an argument and you dont need to know what specific implementation that is
Falco
FalcoOP9mo ago
I don't understand what you mean with and you dont need to know what specific implementation that is
Pobiega
Pobiega9mo ago
one sec
var consoleOutputHandler = new ConsoleOutputHandler();
var fileOutputHandler = new FileOutputHandler();
var databaseOutputHandler = new DatabaseOutputHandler();

var outputHandlers = new List<IOutputHandler>
{
consoleOutputHandler,
fileOutputHandler,
databaseOutputHandler
};

var data = "Hello, World!";
var id = Guid.NewGuid();

foreach (var outputHandler in outputHandlers)
{
outputHandler.Write(id, data);
}
var consoleOutputHandler = new ConsoleOutputHandler();
var fileOutputHandler = new FileOutputHandler();
var databaseOutputHandler = new DatabaseOutputHandler();

var outputHandlers = new List<IOutputHandler>
{
consoleOutputHandler,
fileOutputHandler,
databaseOutputHandler
};

var data = "Hello, World!";
var id = Guid.NewGuid();

foreach (var outputHandler in outputHandlers)
{
outputHandler.Write(id, data);
}
something like this, for one we can refer to all the three outputhandlers as the interface
Falco
FalcoOP9mo ago
and why is that useful why is it more useful than not using an inteface
Angius
Angius9mo ago
You just know that it has a Write method with a given signature. That's all you're concerned with, not where it's written. That's the concern of something else.
// somewhere in settings
IOutputHandler writer = settings["writer"] switch {
"console" => new ConsoleOutputHandler(),
"file" => new FileOutputHandler(),
"database" => new DatabaseOutputHandler(),
};

// somewhere else
writer.Write("hello");
// somewhere in settings
IOutputHandler writer = settings["writer"] switch {
"console" => new ConsoleOutputHandler(),
"file" => new FileOutputHandler(),
"database" => new DatabaseOutputHandler(),
};

// somewhere else
writer.Write("hello");
Pobiega
Pobiega9mo ago
if we dont have an interface, how would you put these three things in one list?
Angius
Angius9mo ago
Lets you set which writer you use once
Pobiega
Pobiega9mo ago
thats another great example
Falco
FalcoOP9mo ago
Ah okay I think I get it But it will become fully clear once I have to implement this myself
Pobiega
Pobiega9mo ago
the core idea here is "abstraction", the ability to refer to something as something else (something less specific)
Angius
Angius9mo ago
Also, if you were to distribute your output handlers as a package, I — the user of the package — could define my own DiscordMessageOutput : IOutputHandler and also use that, to use some webhook to send messages to my Discord server That's the, uh, open-closed principle from SOLID?
Pobiega
Pobiega9mo ago
yeah the O in solid 🙂
Falco
FalcoOP9mo ago
So I could also do this Instead of using IOutputHandler as a interface, I can just call each handler from Main() like this.
C#
ConsoleOutputHandler consoleHandler = New DatabaseOutputHandler();
consoleHandler.Write()
FileOutputHandler fileHandler = New DatabaseOutputHandler();
fileHandler.Write()
C#
ConsoleOutputHandler consoleHandler = New DatabaseOutputHandler();
consoleHandler.Write()
FileOutputHandler fileHandler = New DatabaseOutputHandler();
fileHandler.Write()
But an interface would be more practical because of abstraction, I dont have to create a tightly coupled instance with each specific handler classes to access it. So it's better to just call the interface instead, like this:
c#
IOutputHandler consoleHandler = new ConsoleOutputHandler();
consoleHandler.Write("Hello from console!");

IOutputHandler fileHandler = new FileOutputHandler();
fileHandler.Write("Hello to file!");
c#
IOutputHandler consoleHandler = new ConsoleOutputHandler();
consoleHandler.Write("Hello from console!");

IOutputHandler fileHandler = new FileOutputHandler();
fileHandler.Write("Hello to file!");
Pobiega
Pobiega9mo ago
that, but also the extensibility if your entire system uses the interface instead of a concrete class, someone else can make their own implementation (DiscordMessageOutputHandler) and it will just work Have you heard of dependency injection yet? Interfaces play a big role there, both for multiple implementations, swapping what concrete implementation is used based on a setting, etc
Falco
FalcoOP9mo ago
I've heard of it before. I'm just walking through a C# .Net roadmap make sure I understand everything before I apply for a job. But I'll look into dependency injection. I think it will help understanding interfaces as well. I do get why it's useful but I just need to see some real life examples
No description
Pobiega
Pobiega9mo ago
I made a video on DI a few years ago. Its not perfect, but its fairly short and no bullshit: https://youtu.be/USBoZtGt0QU
Falco
FalcoOP9mo ago
Thx I'll check itg out
Pobiega
Pobiega9mo ago
I really should re-record that some day 😄
leowest
leowest9mo ago
:catpog:
Pobiega
Pobiega9mo ago
Heya leo
leowest
leowest9mo ago
good video, I like how u explain a bit into the singleton vs transient u should make more videos u explain things very well and have a clear voice
Pobiega
Pobiega9mo ago
I have made more videos 🙂 https://www.youtube.com/playlist?list=PLNrLTXgfP7pOOIMcHghOgUOBtrPxrCqcA DI, delegates + events, async/await and tasks, unittests, git, builder pattern, reflection
leowest
leowest9mo ago
I saw those I was saying in general these small 10 minutes explaining 1 thing and doing it well
Pobiega
Pobiega9mo ago
ah yeah
leowest
leowest9mo ago
im a fan of those and u do it very well 😉 sorry hijacked the thread lol
Pobiega
Pobiega9mo ago
I'd like to do more. But I need ideas on what to do and talk about also yeah, sorry Falco
leowest
leowest9mo ago
I be gone sorry falco 😛
Falco
FalcoOP9mo ago
That's okay no worries:)
Want results from more Discord servers?
Add your server