C
C#•9mo ago
JammyG

Calling methods from a base class

Hi, I am completing a beginners c# course and i'm stuck on this question - this section of the course is about polymorphism and inhertiance. The code was already written, I have added an 'ALevelComputerStudent' class, and now I must add functionality to pick which type of student is created. I'm not sure how to do this. I've tried using an interface, but then when I use an interface for 'ALevelComputerStudent' + 'GCSEStudent' classes, i can no longer call methods from the base class. I know there are other ways of doing it , but for the purpose of the question I have one base class which the rest add onto I just cant get my head around when to use inheritance and interfaces without changing all of the existing code written around the 'AStudent' object any help/ explanation would be appreciated 🙂
84 Replies
Pobiega
Pobiega•9mo ago
$paste your code here please, instead of as an attachment
MODiX
MODiX•9mo ago
If your code is too long, you can post to https://paste.mod.gg/ and copy the link into chat for others to see your shared code!
Pobiega
Pobiega•9mo ago
So, all your code here minus the ALevelComputerStudent class were pre-written and given to you? and your goal is to add this new class, and modify the program so that "it asks you what type of student to create: A Level or GCSE"?
JammyG
JammyG•9mo ago
All the code, except from the ALevelCompterStudent class i added was pre written
Pobiega
Pobiega•9mo ago
ok
JammyG
JammyG•9mo ago
yeah, stock, the program only works with GCSE students
Pobiega
Pobiega•9mo ago
I can see that.
JammyG
JammyG•9mo ago
the goal is to add a class ' ALevelStudent' and change the code to work with both
Pobiega
Pobiega•9mo ago
well, you already have the ComputerStudent base class
JammyG
JammyG•9mo ago
BlazeBin - njmzysglayyq
A tool for sharing your source code with the world!
Pobiega
Pobiega•9mo ago
yep okay, so where exactly are you stuck?
JammyG
JammyG•9mo ago
i need to refactor the Main so that it can use ALevelStudent and GCSEStudent im not sure how to do that without getting a compiler error
Pobiega
Pobiega•9mo ago
Yep.. and I can see you've sort of started on that well, can you name a data type that can hold both GCSEComputerStudent and ALevelComputerStudent objects?
JammyG
JammyG•9mo ago
can the base class ComputerStudent do that?
Pobiega
Pobiega•9mo ago
it sure can
JammyG
JammyG•9mo ago
c++
ComputerStudent AStudent;

if (choice == 1)
{
AStudent = new ALevelComputerStudent();
}
else if (choice == 2)
{
AStudent = new GCSEComputerStudent();
}
c++
ComputerStudent AStudent;

if (choice == 1)
{
AStudent = new ALevelComputerStudent();
}
else if (choice == 2)
{
AStudent = new GCSEComputerStudent();
}
Pobiega
Pobiega•9mo ago
there we go
JammyG
JammyG•9mo ago
this gives me an error
Pobiega
Pobiega•9mo ago
does it really?
JammyG
JammyG•9mo ago
No description
Pobiega
Pobiega•9mo ago
thats curious because I have your code, written as is, running on the left here and I don't get that error
JammyG
JammyG•9mo ago
i fixed it, ok, so i have a type computer student that can store either Alevel or GCSE now how do i call methods on it ? it breaks all the code
Pobiega
Pobiega•9mo ago
well, thats the thing both GCSE and ALevel students have methods that the base class does not you'll need to add them to the base class in order to call them
JammyG
JammyG•9mo ago
Is that the only way of doing that like in the prewritten code, GCSE builds upon the ComputerStudentClass
Pobiega
Pobiega•9mo ago
since this assignment is about learning about polymorphism, I'd say... yes
JammyG
JammyG•9mo ago
No description
JammyG
JammyG•9mo ago
it gives me that diagram too the whole thing before it, was about not needing to touch the base class when making new classes how you can just build upon the base class
Pobiega
Pobiega•9mo ago
And you can. But you are trying to add a new "API surface" to the class you could do pattern matching to check if its ALevel or GCSE before calling the method everywhere, but that would be insanity you could also add an interface to both GCSE and ALevel and use that as your variable but unless the assignment actually mentions that, I find that solution a bit weird the obvious solution here is to use virtual/override keywords, if you ask me
JammyG
JammyG•9mo ago
i tried to use an interface originally as then i wouldnt have to touch the base class, but in this course, i haven't gone over Interfaces yet so i thought i might be missing something obvious. this is my first language and these are all new concepts too me
Pobiega
Pobiega•9mo ago
idk, I've only been writing C# for 20 years but my gut instict is to add the new control surface to the base class too, and not have to involve either a ton of if statements or a new interface like, otherwise the whole idea of polymorphism is thrown out the window
JammyG
JammyG•9mo ago
Yeah, overriding the method would make sense, it just confused me that it didnt want me to touch the ComputerStudent class So i need to add methods for ProgressGrade, TargetGrade ect to ComputerStudent, and then override them.
Pobiega
Pobiega•9mo ago
Is there any more information in the assignment? because while you absolutely can solve this without touching ComputerStudent, it will be some of the worst possible code ever written 😄
JammyG
JammyG•9mo ago
nothing that i havent sent so the best way is to use an override?
Pobiega
Pobiega•9mo ago
absolutely look how both ALevel and GCSE have the same method names and types that should be a surefire indicator that it can be abstracted
JammyG
JammyG•9mo ago
this is the next page:
JammyG
JammyG•9mo ago
No description
JammyG
JammyG•9mo ago
its stange because the enitre course has been in order
Pobiega
Pobiega•9mo ago
weird
JammyG
JammyG•9mo ago
not using ideas and concepts it hasnt yet introduced the entire way through so then i got stuck on this question
Pobiega
Pobiega•9mo ago
I wonder if they want you to "do it the hard way" first so that you can later say "omg that would be so much easier if we had override!"
JammyG
JammyG•9mo ago
yeah, thats probably it lmao
Pobiega
Pobiega•9mo ago
would it be possible to ask your teacher/prof?
JammyG
JammyG•9mo ago
I will do, theyve been off for the past two weeks and ive been stuck on this. I found this server while looking for help
Pobiega
Pobiega•9mo ago
something like. "Hey, I have a question. The obvious solution is to add virtual methods to the base class, but since that hasn't been introduced yet..."
JammyG
JammyG•9mo ago
when they get back ill find out which way this question is meant to push you into doing it
Pobiega
Pobiega•9mo ago
yeah
JammyG
JammyG•9mo ago
as the course only uses things its already gone over, i think you are definitley right its just pushing you to do it the long way, and then afterwards tell you a much easier way
Pobiega
Pobiega•9mo ago
So, the solutions I can come up with are: * Virtual methods on the base class * Introduce new interface on subclasses, use that as base variable type * if (AStudent is GCSEComputerStudent gcse) everywhere
JammyG
JammyG•9mo ago
Thank you, youve been very helpful if i used an interface for the new methods in the subclasses, how would i access the methods in the base class, do you always have to cast it
Pobiega
Pobiega•9mo ago
nah, just add those methods to the interface the subclasses implement them via the base class
JammyG
JammyG•9mo ago
so the compiler knows that they are already implemented because of inheriance?
Pobiega
Pobiega•9mo ago
interface was very quick and easy, but feels hacky sorta, yeah more so that subtypes have all the public members of their baseclass they jsut do
JammyG
JammyG•9mo ago
Why would Overriding be prefered? What are the downsides of the interface
Pobiega
Pobiega•9mo ago
because if you make a third class from ComputerStudent it will not work you have essentially introduced a new baseclass, the interface, that your program needs to work I'd prefer to keep ComputerStudent as the core base type
JammyG
JammyG•9mo ago
if the third class used the interface though, would everything still work?
Pobiega
Pobiega•9mo ago
yes and as said, at that point you have two base classes and all your new classes must implement both of them which just seems like extra work, when you could have abstract/virtual methods on the base
JammyG
JammyG•9mo ago
ok, i understand now , i'll use virutal methods then
Pobiega
Pobiega•9mo ago
maybe even abstract, tbh since you dont want them to be optional to implement (I guess)
JammyG
JammyG•9mo ago
Virutal allows a method to be overridden What does abstract do?
Pobiega
Pobiega•9mo ago
it forces a method to be overriden as in "you must implement this method yourself, you cant use the base version"
JammyG
JammyG•9mo ago
ohh thats cool. like an interface but not
Pobiega
Pobiega•9mo ago
yeah you could even make the base class abstract itself that would mean you cant do new ComputerStudent you must use one of the child classes I still think you should ask the teacher/prof first, so you dont get shit grades because you "used stuff not covered yet"
JammyG
JammyG•9mo ago
Nothing i do on assignments like these are graded until i sit my actual exams and in an actual exam you have free reign to solve problems however youd like
Pobiega
Pobiega•9mo ago
okay
JammyG
JammyG•9mo ago
So right now im just learning ways of doing stuff, and hopefully leaning the 'right' way of doing it so now i know, in situations like these its easier to just keep one base class and not mess around with interfaces or weird casting and if statements like i have been
Pobiega
Pobiega•9mo ago
ok, then imho, go with abstract ComputerStudent and add in
abstract int GetTarget();
abstract void CalcNewTarget();
abstract void UpdateProgress();
abstract int GetProgress();
abstract int GetTarget();
abstract void CalcNewTarget();
abstract void UpdateProgress();
abstract int GetProgress();
and also, these methods should just be properties 😄
JammyG
JammyG•9mo ago
if i make an entire class abstract , i wouldnt be able to make a 'new ComputerStudent'
Pobiega
Pobiega•9mo ago
correct
JammyG
JammyG•9mo ago
but i would be able to make a data type of computer student?
Pobiega
Pobiega•9mo ago
but that doesnt seem to be a valid case in the program anyways you must make either an A level, or a GCSE student you can't go "no thanks"
JammyG
JammyG•9mo ago
how would i store it though? like here
Pobiega
Pobiega•9mo ago
ComputerStudent student;

if(blabla)
{
student = new ALevelStudent();
}
ComputerStudent student;

if(blabla)
{
student = new ALevelStudent();
}
JammyG
JammyG•9mo ago
ohh ok. so even if its abstact , i can still use it as a datatype
Pobiega
Pobiega•9mo ago
absolutely you just cant make instances of it
JammyG
JammyG•9mo ago
so not make a 'new ComputerStudent'
Pobiega
Pobiega•9mo ago
exactly
JammyG
JammyG•9mo ago
that makes so much sense and that's perfect for what im doing, thank you
Pobiega
Pobiega•9mo ago
np
JammyG
JammyG•9mo ago
one more thing - why/when would i use an interface instead like how would the scenario need to be different to warrant using an interface
Pobiega
Pobiega•9mo ago
when you have no base logic or fields if your "shared surface" is only methods, then an interface is the way to go
JammyG
JammyG•9mo ago
so if 'class ComputerStudent' didnt exist at all
Pobiega
Pobiega•9mo ago
yeah in this case, all students have names and forms well, and targets... and progress so those two could be moved to the baseclass too 🙂 only UpdateProgress would need to be overriden, I think the rest could be in the base
JammyG
JammyG•9mo ago
yeah that's the only method that's different Thank you for your help
Pobiega
Pobiega•9mo ago
public abstract class StudentBase
{
public StudentBase()
{
Console.WriteLine("Please enter firstname: ");
Firstname = Console.ReadLine()!;
Console.WriteLine("Please enter surname: ");
Surname = Console.ReadLine()!;
Console.WriteLine("Please enter form: ");
Form = Console.ReadLine()!;
}

public string Firstname { get; }
public string Surname { get; }
public string Form { get; }

public string Name => $"{Firstname} {Surname}";

public int Target { get; protected set; }

public int Progress { get; protected set; }

public abstract void CalcNewTarget();
public abstract void UpdateProgress();
}

class ALevelStudent : StudentBase
{
public ALevelStudent()
{
do
{
try // replace with TryParse
{
Console.WriteLine("What target do you want to set for this student? Input a grade between A and U: ");
Target = Char.Parse(Console.ReadLine()!.ToUpper());
}
catch (Exception)
{
Console.WriteLine("You must enter a character between A and U");
}
} while (Target <= 'A' && Target >= 'U');
}

public override void CalcNewTarget()
{
if (Progress > Target)
{
Target = Progress + 1;
}
}

public override void UpdateProgress()
{
do
{
try
{
Console.WriteLine(
"What progress grade do you want to set for this student? Input a grade between A and U");
Progress = int.Parse(Console.ReadLine());
}
catch (Exception)
{
Console.WriteLine("You must enter a character between A and U");
}
} while (Progress <= 'A' && Progress >= 'U');
}
}
public abstract class StudentBase
{
public StudentBase()
{
Console.WriteLine("Please enter firstname: ");
Firstname = Console.ReadLine()!;
Console.WriteLine("Please enter surname: ");
Surname = Console.ReadLine()!;
Console.WriteLine("Please enter form: ");
Form = Console.ReadLine()!;
}

public string Firstname { get; }
public string Surname { get; }
public string Form { get; }

public string Name => $"{Firstname} {Surname}";

public int Target { get; protected set; }

public int Progress { get; protected set; }

public abstract void CalcNewTarget();
public abstract void UpdateProgress();
}

class ALevelStudent : StudentBase
{
public ALevelStudent()
{
do
{
try // replace with TryParse
{
Console.WriteLine("What target do you want to set for this student? Input a grade between A and U: ");
Target = Char.Parse(Console.ReadLine()!.ToUpper());
}
catch (Exception)
{
Console.WriteLine("You must enter a character between A and U");
}
} while (Target <= 'A' && Target >= 'U');
}

public override void CalcNewTarget()
{
if (Progress > Target)
{
Target = Progress + 1;
}
}

public override void UpdateProgress()
{
do
{
try
{
Console.WriteLine(
"What progress grade do you want to set for this student? Input a grade between A and U");
Progress = int.Parse(Console.ReadLine());
}
catch (Exception)
{
Console.WriteLine("You must enter a character between A and U");
}
} while (Progress <= 'A' && Progress >= 'U');
}
}
something like this :p doing stream input in a constructor is very weird in general btw normally you'd just take in parameters, and optionally provide a Create static method that does the input
Want results from more Discord servers?
Add your server