Struggling with one thing about interfaces.
So, I watching a tutorial about IEnumerable and I realized I don't really understand how interfaces work.
What I thought they were: Similar to classes as a level of abstraction, but they normally don't have any default method and instead just have all the methods that NEED to be implemented by their child classes instead.
They also can't be instantiated as objects (but objects of classes that implement them can)
However, I ran into an example close to this:
EXAMPLE:
List<MyClass> MyList = new List<MyClass> {...};
ImyInterface<MyClass> ModifiedList = MyList
(Suppose that ImyInterface is an interface and that MyClass is a class that implements ImyInterface)
Here, the interface name (alongside with the generic indicator <>) is put right before an object named ModifiedList. Which made me think that ModifiedList was an object of the class ImyInterface...
What I don't understand is:
First: That interfaces in theory were supposed to not have objects instantiated directly from them
Second: Even if they could, what is the point of doing this instead of directly using MyList, if MyClass already implements all the ImyInterface methods...
When I asked chat gpt (yeah, Im THAT desperate), it told me that actually ModifiedList is an variable of type ImyInterface, which is possible because variables are not the same as objects, and interfaces can't be objects but they can be variables. Now, I'm not sure if chat gpt is bullshitting me, so I was left unsure, since I was taught that variables were a simplified term, but are actually objects internally too. Which is why I was doubting the AI explanation.
So, regarding the 2 questions I made above, what is the correct explanation?
Sorry for the wall of text, I'm really confused.
35 Replies
for once chatgpt isn't BSing you
the reason interfaces exist is to allow code to use any kind of object as long as it implements certain methods
for example, LINQ is built on IEnumerable which means it works with any collection type that implements that interface
So, variables and objects are actually separate things?
it's the same deal as an abstract class
you can't instantiate it directly, but you can have objects that derive from it
Im just confused because its typed in the same convention as a direct object instance
like
MyClass myInstance
The class comes right before of the name of this instance. So it just looks like its doing the same
that isn't an instance, it's just a variable (technically uninitialized)
you don't create an instance until you do
new MyClass()
It seems i really dont understand a thing then 😂😂
I thought any object or variable was an instance.
as far as classes are concerned, variables hold references to instances of objects
kind of like pointers in C++ if you've learned that
uhh i learned C so i kinda know about pointers
(long time ago)
Does a variable that isnt an instance (no new() after) does anything in practice?
it's uninitialized, and you can't use it until you've assigned a value to it or you'll get an error
when you do something like
ImyInterface<MyClass> ModifiedList = MyList
the actual object is still a List<MyClass>
but you can only access the members defined by ImyInterface<MyClass>
through the variableIts an empty variable, but what does saying it belongs to an interface do?
i wouldn't say that, it doesn't make sense
variables have data types which define what values they're allowed to hold
if your variable is an
IMyThingy
then it can hold a reference to any object that implements the IMyThingy
interfaceSo you are forcing the variable's future instance to be from a class that implements that interface?
is that it?
you could say that
hmm
it's the same reason you can't say
int myNumber = "a string"
, the types aren't compatible because a string is not an int
but when you're dealing with classes and inheritance, a variable can hold objects derived from its defined data type in addition to that data type itselfSo you are saying: This variable holds any, but only, types/classes that implement this Interface
would that be correct?
exactly
Hmmmmmmm
yeah im starting to grasp
the reason you can do it is because derived types still have the same original "shape" as their parent class/interface
so they can do everything the parent can do, so they fit into the variable
they might have extra stuff but that's fine, because they still have the stuff needed to "be" that parent type
In a way, would be correct to say we dont refer to instances directly, but we reference and point them via variables in reality?
for classes (reference types in general) yes, the variable never actually holds the data of the object
the object lives somewhere else and the variable just tells you how to find it
brb
Last thing, if I'm doing:
ImyInterface<MyClass> ModifiedList = MyList
(in which MyList was a List<MyClass> itself)
Why wouldn't I just directly use the variable MyList? Why would I need to make a variable of any type that implements ImyInterface, and then proceed to define which one it is? Couldnt I just directly use MyList for whatever I do?
No hurry
Maybe so you can change in other point of the code where does that variable "points to", like another instance of another type (but, that also implements that interface)
Because if it was MyList, I wouldn't be able to change the variable to another instance of another type?
Just my theory idk if it makes any sense.
ImyInterface<MyClass> ModifiedList = MyList
Assuming List
somehow implements ImyInterface
You typically wouldn't just use it like that but instead
Given a function
void MyFunc(ImyInterface<MyClass> classList)
You can pass
MyFunc(MyList)
But also beacuse the method takes n generic interface ImyInterface<MyClass>
you can pass any class that implements said interfaces not just List<MyClass>
Sorry If i misunderstood what you said, but are you saying something close to what I said here? :
.
No it's different
Let's take another example
interface IAnimal
That interfaces has a method
void Behaviour()
And we have 3 classes, cat, dog, rabbit
Let's say we also have a method that calls that method in the animal so for example
void SimulateAnimal(Cat cat)
void SimulateAnimal(Dog dog)
void SimulateAnimal(Rabbit rabbit)
As you can see we have 3 duplicates even though it makes sense to have one
So intead we could do
void SimulateAnimal(IAnimal animal)
We could then pass a cat, dog or rabbit to that method(please keep going ill just brb real quick)
This makes your code way more maintainable
Another example let's say you need to log something
And you don't really concern yourself where these logs are saved, maybe written to a console, or saved to file
In this case it would make more sense to take an
ILogger
instead of ConsoleLogger
and FileLogger
Yeah that makes a lot of sense
Thanks guys, you are all super smart and helpful. 🙏🙏
(Idk If I can still ask about it in the same thread) What about methods with interface type before it?
Does that mean the return type can only be a class that inherits from that interface, otherwise it sends an error?
example: ImyInterface<T> CoolMethod() { ...
yes, this is general OOP
if the return type is
IMyInterface<T>
then whatever value is returned must implement IMyInterface<T>
then you use an exception catch thingy to let the caller know if its not? otherwise wouldnt it crash?
probably yeah im just new to programming in general :Kek:
no, because you'll never run code that breaks this rule
it's a compiler error
the compiler knows what has to be returned and what you're returning, and if it won't work it won't compile
what if the inner working of the method changes with user input and therefore can be or not be the correct type on the return depending on circumstances?
does the compiler still not run it just bcs of the possibility?
like i said, that code would be invalid
i see, thank you
it must always return a compatible type or it won't compile