C
C#2w ago

overriding methods

I have multiple questions: 1) What is the benefit of declaring a base method as virtual before overriding it in an inheriting class? This is my understanding: it allows calling the override despite casting to the base class. Is this correct? 2) What is the difference between overriding a method, and hiding a method? As in, what does the new keyword do exactly?
51 Replies
Becquerel
Becquerel2w ago
you have to declare methods as virtual (or abstract) to override them. you can't override them otherwise the new keyword changes nothing about the semantics of your program. it just stops the compiler from giving you a warning, because it now assumes you're using a method of the same name in the parent and child deliberately
fæ
OP2w ago
So what is the difference between these two?
No description
No description
Anton
Anton2w ago
1) if you don't, it'll call the method in the base class 2) you tell the compiler you mean the thing at 1) to happen $code
MODiX
MODiX2w ago
To post C# code type the following: ```cs // code here ``` Get an example by typing $codegif in chat For longer snippets, use: https://paste.mod.gg/
Anton
Anton2w ago
put some code in the implementation try calling it yourself through the base class and through the child class
fæ
OP2w ago
Alright
Anton
Anton2w ago
I'd also recommend to make the base class abstract in such cases
fæ
OP2w ago
So
Anton
Anton2w ago
make stuff you inherit abstract if possible make child classes sealed if you don't expect to inherit them further
fæ
OP2w ago
a virtual class being overriden prevents the base class default implementation from being ran, even if the instance's type is the parent class
Anton
Anton2w ago
but lastly, don't inherit if possible
fæ
OP2w ago
the CLR will infer the proper implementation this sounds useful if i have multiple classes inheriting from one class i could make uhhh List<baseclass> for example and ensure that the implemented .Display() will run and not the base's i want to nail the oop stuff first, i need to fully and properly grok every single thing about these concepts. once i do, i'll try to implement such advice
Anton
Anton2w ago
that is how it's used
fæ
OP2w ago
im guessing it's the "composition over inheritence" argument, i hear you
Anton
Anton2w ago
it's not the best idea though
fæ
OP2w ago
how would you do it? also, why an abstract method over a virtual one?
Anton
Anton2w ago
It depends. Either make a separate system that decides what to call, or store an interface with the implementation somewhere, possible in a field or another list. I wouldn't want Person to both store data and declare virtual methods. It's harder to redefine things granularly like this, and reuse existing implementing instances. Some state may be shared, but you'd have to store it in the derived class anyway. It's less flexible and always produces kind of a mess
fæ
OP2w ago
abstract requires a lack of body
Anton
Anton2w ago
not method necessarily, class
fæ
OP2w ago
why an abstract class, so it doesnt get instanciated?
Anton
Anton2w ago
if you go abstract method, there's no benefit over using a base class over an interface
fæ
OP2w ago
semantics maybe?
Anton
Anton2w ago
so it's clear it's designed for inheritance and shouldn't be used for other purposes
fæ
OP2w ago
so my last question is, what's the difference between abstract class and interface
Anton
Anton2w ago
the only instance where you'd want a base class, is when you wrap an interface implementation, calling into a virtual method, and have the child override that instead in my experience that's like one of the very few use cases abstract class can have fields
fæ
OP2w ago
interface can't have properties or fields?
Anton
Anton2w ago
fields specifically
fæ
OP2w ago
thats weird
Anton
Anton2w ago
and you can only implement a single base class
fæ
OP2w ago
properties are backed by fields, so why can you have properties but not fields
Anton
Anton2w ago
but any number of interfaces they're sort of virtual on interfaces they're backed by fields when they're on a class when they're on an interface, it just means get and set methods need to be present it doesn't enforce the presence of a field
fæ
OP2w ago
No description
Anton
Anton2w ago
so the implementer can store that count however they want
fæ
OP2w ago
alright
Anton
Anton2w ago
it doesn't have to be in a field
fæ
OP2w ago
so how does the CLR infer the type when an object is stored as its base class? for example
Anton
Anton2w ago
it has a hidden type info pointer field it points at another object in memory specific to the type of that class every class has this
fæ
OP2w ago
class Person{/**/}

class Senior : Person {/**/}
class Junior : Person {/**/}

List<Person> list = new List<Person> { new Senior(), new Junior() } //the proper implementations are still remembered here
class Person{/**/}

class Senior : Person {/**/}
class Junior : Person {/**/}

List<Person> list = new List<Person> { new Senior(), new Junior() } //the proper implementations are still remembered here
ahh okay
Anton
Anton2w ago
that object in memory has a list where it stores the function pointers to the method implementations of the interfaces or the base class it implements when you call a virtual method indirectly (through the base class for example, or through the child when the child class is not sealed) the CLR walks through that list at runtime to find the entry for the base type (the one which defines the virtual method) then it calls the method indirectly via the function pointer stored along in that entry when it's not virtual, or the compiler can determine at compile time (statically) which method will be called, at runtime none of this will happen it'd just jump to the right instruction from the start Unless you actually need polymorphism for some purpose, you're better off simulating the type of person yourself with an enum Especially for simple programs, this is a good idea Less indirection means easier to debug and usually easier to understand
fæ
OP2w ago
enum PersonType
{
Junior, Senior
}
enum PersonType
{
Junior, Senior
}
?
Anton
Anton2w ago
yeah, and then a switch over this to determine what action to take
fæ
OP2w ago
This is a more functional approach right? This is how i'd do it in JS
Anton
Anton2w ago
you'll know it when you'll need polymorphism yes
fæ
OP2w ago
or I could have a property in the Person class Person.AgeBracket
Anton
Anton2w ago
you can do pattern matching over hierarchies too, to be fair It's just open what all the subtypes are with an enum it's clear that those are the only allowed options and those are the ones you have to implement
fæ
OP2w ago
heh, it's the next section
No description
Anton
Anton2w ago
tbh never done this tagging by subtyping. I usually reach out for a manually written tagged union. But I don't think it's bad necessarily
fæ
OP2w ago
@Anton what happens when there's a chain of inheritence involving overriding virtual base method?
public class A
{
public virtual void Method() { }
}
public class B : A
{
public override void Method() { }
}
public class C : B
{
public override void Method() { } //does it override B.Method, or A.Method?
}
public class A
{
public virtual void Method() { }
}
public class B : A
{
public override void Method() { }
}
public class C : B
{
public override void Method() { } //does it override B.Method, or A.Method?
}
Gax
Gax2w ago
C's implementation gets called instead of B's the children overrides the immediate parent's methods It's faster if you simply put a different Console.WriteLine and run the code yourself to mess with it rather than asking
MODiX
MODiX2w ago
Gax
REPL Result: Success
var foo = new C();
foo.Method();
A bar = (A)foo;
bar.Method();
public class A
{
public virtual void Method()
{
Console.WriteLine("A");
}
}

public class B : A
{
public override void Method()
{
Console.WriteLine("B");
}
}

public class C : B
{
public override void Method()
{
Console.WriteLine("C");
}
}
var foo = new C();
foo.Method();
A bar = (A)foo;
bar.Method();
public class A
{
public virtual void Method()
{
Console.WriteLine("A");
}
}

public class B : A
{
public override void Method()
{
Console.WriteLine("B");
}
}

public class C : B
{
public override void Method()
{
Console.WriteLine("C");
}
}
Console Output
C
C
C
C
Compile: 577.813ms | Execution: 32.138ms | React with ❌ to remove this embed.
Gax
Gax2w ago
ignore broken indentation but as you can see even after casting C to A, it still executes C's implementation
Want results from more Discord servers?
Add your server