I have a base class with three field, but instead of initializing its field the normal way like this:
class ParentClass
{
public string Name { get; set; }
public string Family { get; set; }
public string Address { get; set; }
public ParentClass(string Name, string Family, string Address)
{
this.Name = Name;
this.Family = Family;
this.Address = Address;
}
}
class ChildClass : ParentClass
{
public int StudentID { get; set; }
public int StudentScore { get; set; }
public ChildClass(string Name, string Family, string Address, int StudentID, int StudentScore)
: base(Name, Family, Address)
{
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
static void Main(string[] args)
{
var Pro = new ChildClass("John", "Greene", "45 Street", 76, 25);
Console.WriteLine(Pro.Name + Pro.Family + Pro.Address + Pro.StudentID + Pro.StudentScore);
}
}
I’ve initialized the fields in the ChildClass constructor without explicitly calling the base class constructor like this:
class ParentClass
{
public string Name { get; set; }
public string Family { get; set; }
public string Address { get; set; }
}
class ChildClass : ParentClass
{
public int StudentID { get; set; }
public int StudentScore { get; set; }
public ChildClass(int StudentID, int StudentScore)
{
Name = "John";
Family = "Greene";
Address = "45 Street";
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
static void Main(string[] args)
{
var Pro = new ChildClass(76, 25);
Console.WriteLine(Pro.Name + Pro.Family + Pro.Address + Pro.StudentID + Pro.StudentScore);
}
}
I know I could have initialized the parent class’s field in the parent class itself and this is a bogus example, but I was wondering if it is considered a good practice to do something like that in real life and more complex situations, is there any reason why I shouldn’t do something like this? as to not explicitly call the base class constructor?
Edit: I'm more concerned about not explicitly call the base class constructor and initializing it in subclass part, so I've edited the last part that mentioned the fields being exposed out.
As you've already seen, the fields are already "exposed". Your could still get to those variables from the derived class in the first example.
As to not using a base class constructor being good practice, I would say not. By only having a parameterized base class constructor, you are making sure that future implementers of that class initialize the base class properties. For example, in your second I could write:
public ChildClass(int StudentID, int StudentScore)
{
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
With no errors. Other than that there are very few differences between your samples.
Related
My question is simple.
I am working with a testcase given to me in C#.
In this test case they have a Parent class containing all the methods and subclasses that will call those methods.
So as far as I know. You can do that by:
Class object = new Class(arguments);
Then call the parent methods like this object.Method()
Now the test I am working with has it written like this: Class.Method()
So just to make my question more clear here is an example of what they have:
Book harryPotterBook = new Book { title = "Harry Potter" };
var savedBook = Book.Find(harryPotterBook.Id);
and here is what I understand it should be:
var savedBook = harryPotterBook.Find(harryPotterBook.Id);
So is this possible? I just want to know what I am missing here.
Thank you.
I'm not sure I understand what you're trying to do right now, because in your example, you seem to be asking how to generate a class with a constructor. If you want to create a class constructor you have to write it like this:
public class Class
{
string name;
public Class(string pName)
{
name = pName;
}
}
Otherwise, if you know that this class is going to be used often as a standard. You can use interfaces:
interface IBasicClass
{
string name { get; set; }
string description { get; set; }
int numberOfPage { get; set; }
int currentPage { get; set; }
void NextPage();
void PreviousPage();
}
public class BasicClass : IBasicClass
{
public string name { get; set; }
public string description { get; set; }
public int numberOfPage { get; set; }
public int currentPage { get; set; }
//Default Constructor
public BasicClass()
{
name = "";
description = "";
numberOfPage = 0;
currentPage = 0;
}
//Constructor
public BasicClass(string pName, string pDescription, int pNumberOfPage)
{
name = pName;
description = pDescription;
numberOfPage = pNumberOfPage;
}
public void PreviousPage()
{
--currentPage;
}
public void NextPage()
{
++currentPage;
}
}
public class Class : MonoBehaviour
{
BasicClass _basicClass;
BasicClass _basicClass2;
void Start()
{
_basicClass = new BasicClass();
_basicClass2 = new BasicClass("Books", "It's a good book", 1);
}
void Update()
{
_basicClass.NextPage();
_basicClass2.NextPage();
}
}
I'm very new to programming and I couldnt find an exact answer for my question by googling it so hopefully i'll make it as simple as possible to understand.
My public class MotherClass() has public int Id which should show current number stored in public static int idCounter. I want to inherit/share same idCounter in my public class ChildClass : MotherClass.
So when i make for ex. 2 new MotherClass() objects and lets say 2 new ChildClass() objects, their Id's should be: 1,2,3,4 (shared) and not like 1,2 and 1,2 (different counter for each class).
This is what i have:
public class MotherClass(){
public static int idCounter {get; set;}
public int Id { get; set; }
public string Name { get; set; }
static MotherClass(){
idCounter = 1;
}
public MotherClass(string name, int id = -1){
if(id == -1)
Id = idCounter++;
Name = name;
}
public class ChildClass : MotherClass{
public double Price { get; set; }
public ChildClass(string name, double price int id =-1) : base(name,id){
Price = price;
}
}
Here's one way you could do it:
public class MotherClass
{
public static int IdCounter { get; private set; } = 1;
public int Id { get; } = IdCounter++;
}
public class ChildClass : MotherClass { }
Each time you create a new MotherClass or ChildClass, IdCounter will be incremented.
Example:
Console.WriteLine(new MotherClass().Id); // 1
Console.WriteLine(new MotherClass().Id); // 2
Console.WriteLine(new ChildClass().Id); // 3
You should make the setter of IdCounter private then other classes cannot modify the value.
Ok, so here's the problem. I have an interface IBook, which includes property Name. There is two classes which inherit from the IBook and add their own property Genre. I wanna create a Dictionary or a List and add all kinds of books there and access them by string and their properties so I made it Dictionary. In the example, I can access books["LOTR"].Name but not books["LOTR"].Genre, propably because Name is property of the IBook interface but Genre is property of the class that inherits from the IBook.
Is it possible to make the Dictionary or List work with the interface type and still be able to access all the inheriting class properties as well, or should I use an array or something?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp124
{
interface IBook
{
string Name { get; set; }
}
public class FantasyBook:IBook
{
string name;
string genre;
public string Name
{
get { return name; }
set { name = value; }
}
public string Genre
{
get { return genre; }
set { genre = value; }
}
}
public class HorrorBook : IBook
{
string name;
string genre;
public string Name
{
get { return name; }
set { name = value; }
}
public string Genre
{
get { return genre; }
set { genre = value; }
}
}
class Program
{
static void Main(string[] args)
{
FantasyBook LordOfTheRings = new FantasyBook();
HorrorBook Frankenstein = new HorrorBook();
Dictionary<string, IBook> books = new Dictionary<string,
IBook>();
books.Add("LOTR", LordOfTheRings);
books.Add("Frankenstein", Frankenstein);
books["LOTR"].Name = "Lord Of The Rings";
books["LOTR"].Genre = "Fantasy";
Console.ReadLine();
}
}
}
An alternative approach is to add another layer of interface with Genre and use pattern matching for accessing the properties:
interface IBook
{
string Name { get; set; }
}
interface IBookWithGenre : IBook
{
string Genre { get; set; }
}
public class FantasyBook : IBookWithGenre
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class HorrorBook : IBookWithGenre
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class SimpleBook : IBook
{
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
FantasyBook LordOfTheRings = new FantasyBook();
HorrorBook Frankenstein = new HorrorBook();
SimpleBook abook = new SimpleBook();
var books = new Dictionary<string, IBook>
{
{ "LOTR", LordOfTheRings },
{ "Frankenstein", Frankenstein },
{ "Simple", abook },
};
books["LOTR"].Name = "Lord Of The Rings";
if (books["LOTR"] is IBookWithGenre withGenre)
{
withGenre.Genre = "Fantasy";
}
Console.ReadLine();
}
}
The comments are pretty much on point - you cannot do that as the compiler will examine available members on the IBook (since you declared it) and will not let you shoot yourself in the foot by trying to access a property that's not defined there. This is static type checking.
But let's for a second imagine you don't care about type safety and performance. It turns out, you have an option then. Well, sort of...as you will still have to give up your specific IBook for dynamic
interface IBook {
string Name { get; set; }
}
public class FantasyBook : IBook
{
public string Name { get; set; }
public string Genre { get; set; }
}
public class HorrorBook : IBook
{
public string Name {get;set;}
public string Genre {get;set;}
}
public class BadaBook : IBook // so I added this new class that does not implement Genre to illustrate a point
{
public string Name { get; set; }
}
static void Main(string[] args)
{
var LordOfTheRings = new FantasyBook();
var Frankenstein = new HorrorBook();
var Badaboom = new BadaBook();
Dictionary<string, dynamic> books = new Dictionary<string, dynamic>();
books.Add("LOTR", LordOfTheRings);
books.Add("Frankenstein", Frankenstein);
books.Add("Badaboom", Badaboom);
books["LOTR"].Name = "Lord Of The Rings";
books["LOTR"].Genre = "Fantasy";
books["Badaboom"].Name = "We can easily assign Name as it is defined. No problem here";
books["Badaboom"].Genre = "But we will miserably fail here"; // RuntimeBinderException: 'UserQuery.BadaBook' does not contain a definition for 'Genre'
Console.ReadLine();
}
Check out dynamic for further reading. It comes with the risks outlined in my example as well as performance penalties. It's not bad per se, it just needs to be taken in moderation.
I have a problem using ValueInjecter for derived classes:
public class A
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class B : A
{
public int Age { get; set; }
}
public static void main()
{
var b = new B()
{
Id = Guid.NewGuid(),
Name = "Test!",
Age = 47
};
var a = new A();
a.InjectFrom(b);
}
Injecter does not seem to copy the properties of the derived class.
I then tried to use the Clone convention and debugged the different calls to the methods, but I could not even see calls for the properties of the derived class. Only the properties directly on class A were called.
What am I doing wrong?
Best regards,
Andreas Kroll
My person class:
class Person
{
public string FirstName { get; private set; }
public string LastName { get; private set; }
public int Age { get; private set; }
public Person(string firstName,string LastName,int age)
{
this.FirstName = firstName;
this.LastName = LastName;
this.Age = age;
}
public override string ToString()
{
return this.FirstName + " " + this.LastName + " " + this.Age;
}
}
Main:
class Program
{
static void Main(string[] args)
{
Person sallyPerson = new Person("Sally", "Solomon",23);
}
}
Lets say I want to change the Firstname and Age of the person, how would I go about doing so? The FirstName and Age properties are set privately.
You could make the properties public -
class Person
{
// changed private set; to set;
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
So I just realized, all of the answers are assuming that the question you're asking is literally the question you're asking, rather than just an example. But perhaps you were just using it as an example, and you actually need to set a private property of an object that you don't control the source of? In which case, I would say, that's generally a bad idea, but if you really need to do it anyway, there is a way. That way is called "reflection" (this being just one of many kind-of-sketchy things you can do with reflection if you really want). This is a question that you might want to look at, if that is actually what you're after.
More likely, though, the correct response is just don't have the properties be private if you control the source for that class, and are going to want to change them.
class Program
{
static void Main(string[] args)
{
Person sallyPerson = new Person("Sally", "Solomon",23);
sallyPerson = new Person("Newname", "Newvalue", 23);
}
}
This would be one way, another way would be to add methods in the Person object:
public void UpdateFirstName(string newName)
{
this.FirstName = newName;
}
and do sallyPerson.UpdateFirstName("newName");
Or make the properties public with public set and get
The class has been set up as Immutable meaning that once an instance of this class has been constructed it's properties cannot be modified. If you want to be able to construct this class and them modify it's properties you need to make the classes set properties to be public, like so:
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
I'm hoping this is a homework question, otherwise #Brandon Cuff's answer is the obvious one.
Alternatively, you could expose methods to set the fields:
class Person
{
public void SetFirstName(string value)
{
this.FirstName = value;
}
}