Below shows my 3 classes: Person, Employee and SalaryEmployee.
Each class (from the right) inherits the class from the left side. E.g: SalaryEmployee inherits from Employee.
class Person
{
private string address;
private string name;
public Person(string givenName, string givenAddress)
{
name = givenName;
address = givenAddress;
}
public virtual void outputName()
{
MessageBox.Show("My name is " + name);
}
public void outputAddress()
{
MessageBox.Show("My address is " + address);
}
public void setName(string newName)
{
name = newName;
}
public void setAddress(string newAddress)
{
address = newAddress;
}
}
class Employee : Person
{
private string NINumber;
public Employee(string givenName, string givenAddress) : base(givenName, givenAddress)
{
}
public void setNINumber(string givenNumber)
{
NINumber = givenNumber;
}
public void getNINumber()
{
MessageBox.Show("My National Insurance Number is " + NINumber);
}
}
class SalaryEmployee : Employee
{
private string name;
private string address;
public SalaryEmployee(string givenName, string givenAddress) : base(givenName, givenAddress)
{
name = givenName; address = givenAddress;
}
public override void outputName()
{
MessageBox.Show("My name is " + "S_" + name);
}
}
OOP is fairly new to me and I am trying to get the hang of inheritance. The problem I am facing is I have created an object called 'PersonFive':
SalaryEmployee personFive = new SalaryEmployee("Bob", "North Pole");
// Ignore the address 'North pole' I have used as a parameter, it's just used for this example.
I am able to call the .outputName() method, the output will be:
"My name is Bob"
However, the base method is called instead of the overridden method. The output I wanted it to give me was "My name is S_Bob"
It's working for me, you might didn't post the actual code that makes the error.
Related
I have the following code:
public class UnitManager
{
public string Name { get; set; }
public string Firstname { get; set; }
public UnitManager(string name, string firstname)
{
this.Name = name;
this.Firstname = firstname;
}
}
class Other
{
}
class Program
{
static void Main(string[] args)
{
var player1 = new UnitManager("p1Name", "p1FirstName");
var player2 = new UnitManager("p2Name", "p2FirstName");
}
}
So, I have created 2 objects in the Program class.
what I'd like to do is access those instances from inside the Other class to // do stuff.
For example, access player name, put a title in his name, then assess player2 and put another title.
please, keep in mind, this is just an exemple, i'm not actually planning on using this, i'm just trying to grasp the concept.
I think you can write UnitManager a property in Other class, set the UnitManager
public class Other
{
public UnitManager manager1{ get; set; }
}
or write a method the pass UnitManager instance as parameter.
public class Other
{
public void SetTitle(UnitManager m1) {
// do your logic
}
}
Thank you all, i finally understood :)
Here's how i got it working with your help:
public class UnitManager
{
public string Name { get; set; }
public string Firstname { get; set; }
public UnitManager(string name, string firstname)
{
this.Name = name;
this.Firstname = firstname;
}
}
class Other
{
public static void AddTitle(UnitManager myUnit)
{
var titlePlusFullName = ("The Legendary" + " " + myUnit.Name + " " + myUnit.Firstname);
myUnit.Name = titlePlusFullName;
}
}
class Program
{
static void Main(string[] args)
{
var player1 = new UnitManager("john", "smith");
var player2 = new UnitManager("jen", "doe");
Other oT = new Other();
Other.AddTitle(player1);
Console.WriteLine("Player 1 name: " + player1.Name);
}
}
it displays full name + title.
I think you might want something like this:
public class UnitManager
{
public string Name { get; set; }
public string Firstname { get; set; }
public UnitManager(string name, string firstname)
{
this.Name = name;
this.Firstname = firstname;
}
}
public class Other
{
public void doSomething(UnitManager myUnit) {
//do something with each unit manager
}
}
public class Program
{
static void Main(string[] args)
{
//create an object of type UnitManager and place it into variable player1
var player1 = new UnitManager("p1Name", "p1FirstName");
//create an object of type UnitManager and place it into variable player2
var player2 = new UnitManager("p2Name", "p2FirstName");
//create an instance of the class Other
Other ot = new Other();
//call the method within the instantiated class ot (of type Other) and
//pass it the instance of the object UnitManager with a name
//of player1
result1 = ot.doSomething(player1);
result2 = ot.doSomething(player2);
}
}
If you have exactly 2 instances (players), why not create them within UnitManager?
// sealed: since we have 2 instances only we don't want to
// inherit (and create) derived classes
public sealed class UnitManager
{
public string Name { get; set; }
public string Firstname { get; set; }
// private: since we have 2 intances only we don't want to expose the constructor
private UnitManager(string name, string firstname)
{
this.Name = name;
this.Firstname = firstname;
}
// Think over renaming these fields: say, Player and Computer
public static readonly UnitManager Player1 = new UnitManager("p1Name", "p1FirstName");
public static readonly UnitManager Player2 = new UnitManager("p2Name", "p2FirstName");
}
Then address them as UnitManager.Player1 (UnitManager.Player2) e.g.
class Program
{
static void Main(string[] args)
{
UnitManager.Player1.Name = "First Name";
UnitManager.Player2.Name = "Second Name";
...
}
}
Or even (with a help of static import):
using static MyNamepace.UnitManager;
...
class Other
{
public void DoSomething()
{
// We don't have now put it as UnitManager.Player1
string name1 = Player1.Name;
...
}
}
I'm currently trying to C# asp.net and this was one of my old labs that I never attended and I'm looking for help on it.
Basically I want to be able to store details of the person I input onto a webpage and then bring them up in the About page.
I keep getting the error:
Error 1: Inconsistent accessibility: field type 'System.Collections.Generic.IList<Lab5.Person>' is less accessible than field 'Lab5._Default.PresentPerson'
My code:
Class Person:
{
class Person
{
string age;
string name;
string dob;
string telNo;
string gender;
string address;
public string Age
{
get { return age; }
set { age = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public string DOB
{
get { return dob; }
set { dob = value; }
}
public string TelNo
{
get { return telNo; }
set { telNo = value; }
}
public string Gender
{
get { return gender; }
set { gender = value; }
}
public string Address
{
get { return address; }
set { address = value; }
}
public string enterPerson;
public Person(string name, string age, string dob, string telNo, string gender, string address)
{
Name = name;
Age = age;
DOB = dob;
TelNo = telNo;
Gender = gender;
Address = address;
}
public string PresentPerson()
{
return enterPerson = "Name: " + Name + "\n" + "Age: " + Age + "\n" + "Date of Birth: "
+ DOB + "\n" + "Telephone Number: " + TelNo + "\n" + "Gender: " + Gender + "\n" + "Address: "
+ Address;
}
}
}
Code behind the Default page:
{
public partial class _Default : Page
{
public static IList<Person> personList = new List<Person>();
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("You have successfully added a Person!");
personList.Add(new Person(TextBox1.Text, TextBox2.Text,
TextBox3.Text, TextBox4.Text, DropDownList1.Text, TextBox5.Text));
Session["Person"] = personList;
}
}
}
and code in the About page:
{
public partial class About : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Session["PersonList"] != null)
{
IList<Person> personList = (List<Person>)Session["PersonList"];
foreach (Person p in personList)
{
Response.Write(string.Format("Name :{0} and Age :{1}, DOB :{2}, TelNo, :{3}, Gender :{4}, Address :{5} ", p.Name, p.Age, p.DOB, p.TelNo, p.Gender, p.Address));
Response.Write("<br/>");
}
}
}
}
}
I know that there's probably a load of issues, but I am new to C#!
Your _Default page has a list of Person field. Person is internal, but _Default is public.
This is the inconsistency - clients of _Default would have access to these Person objects when they shouldn't. To fix, make Person public:
public class Person
{
....
You could, alternatively, make the field internal or private.
private static IList<Person> personList = new List<Person>();
You need to change class Person to public class Person
If something is public like the _Default class in your example every public thing on it also needs to be public. You can't have a public thing that is in fact private.
Have two questions assigned for homework, both of the same form, so I'll post the first one:
"Create an Employee class. Items to include as data members are
employee number, name, date of hire, job description, department, and
monthly salary. The class is often used to display an alphabetical listing of all employees. Include appropriate constructors and properties. Override the
ToString ( ) method to return all data members. Create a second class
to test your Employee class."
I've created an Employee class with the proper variables, properties, and constructors, but am having trouble "testing" it through a second class. The code I have written runs without errors, but doesn't display anything (presumably the goal of the testing). Where am I going wrong in the calling section?
Employee info section:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EmployeeProgram
{
public class employee
{
private int employeeNumber;
private string name;
private string hiredate;
private int monthlySalary;
private string description;
private string department;
public employee(int employeeNumber, string name, string dateOfHire, int monthlySalary, string description, string department)
{
this.employeeNumber = 321;
this.name = "Alex";
this.hiredate = "01/02/15";
this.monthlySalary = 2500;
this.description = "Corporate grunt";
this.department = "Sales";
}
public int EmployeeNumber
{
get
{
return employeeNumber;
}
set
{
employeeNumber = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public string Hiredate
{
get
{
return hiredate;
}
set
{
hiredate = value;
}
}
public int MonthlySalary
{
get
{
return monthlySalary;
}
set
{
monthlySalary = value;
}
}
public string Department
{
get
{
return department;
}
set
{
department = value;
}
}
public string Description
{
get
{
return description;
}
set
{
description = value;
}
}
public override string ToString()
{
return "Employee ID: " + employeeNumber +
"Employee Name: " + name +
"Employee Hire Date: " + hiredate +
"Employee Monthly Salary: " + monthlySalary +
"Employee Description: " + description +
"Employee Department: " + department;
}
public void Print()
{
Console.WriteLine(this.ToString());
}
}
"Calling section"
namespace employee
{
public class employeeApp
{
public static void Main()
{
EmployeeProgram.employee Employee = new EmployeeProgram.employee(321, "Alex", "1/02/15", 2500, "Corporate grunt", "Sales");
}
}
}
You need to invoke the Print() method of EmployeeProgram.employee in the main() method.
namespace employee
{
public class employeeApp
{
public static void Main()
{
EmployeeProgram.employee Employee = new EmployeeProgram.employee(321, "Alex", "1/02/15", 2500, "Corporate grunt", "Sales");
Employee.Print();
}
}
}
But as others have pointed out, there are a lot of issues with your code:
Class name should be in Pascal casing, i.e., start with a capital letter. Hence, it should be EmployeeProgram.Employee and not EmployeeProgram.employee
Private variables generally follow Camel casing, i.e., start with small letter. Hence, it should be meployee instead of Employee in your Main() method.
You can reduce the boilerplate code in your employee class by making use to auto-properties.
Parameter dateOfHire should be a DateTime object instead of string.
Parameters like monthlySalary are generally of type decimal and not int.
I have class Person, two child classes Staff and Student, interface IPerson. Also I have a class Database and class Gateway. Class Database has
private string name = "username";
and method
public void getName() {return id;}
Both Staff and Student have getName() methods. I need to create request getName() from student and staff classes to database through gateway. Class Gateway has to check if method getName() was requested by Staff (then return id) or Student (then return "Go away!").
Can anyone please help me with that. I was thinking about using Gateway as an interface of Database class, but because I am only trying to learn C#, I don't really know how to do that. Or maybe there's a better way of doing this... Please help
Thanks
here's some code:
public class Staff : Person
{
public Staff() {}
public Staff(string id): base(id) {}
public override string getName()
{
throw new NotImplementedException();
}
public override void Update(object o)
{
Console.WriteLine(id + " notified that {1}", id, o.ToString());
}
public override void UpdateMessage(object p)
{
Console.WriteLine(id + " notified about new message in chat: {1}", id, p.ToString());
}
}
public class Student : Person
{
public Student() {}
public Student(string id): base(id) {}
public override string getName()
{
throw new NotImplementedException();
}
public override void Update(object o)
{
Console.WriteLine(id +" notified that {1}", id, o.ToString());
}
public override void UpdateMessage(object p)
{
Console.WriteLine("Message for " + id + " {1}", id, p.ToString());
}
}
public abstract class Person : IPerson
{
public string id;
public Person() { }
public abstract string getName();
public Person(string i) { this.id = i; }
public abstract void Update(Object o);
public abstract void UpdateMessage(Object p);
}
public interface IPerson
{
void Update(Object o);
void UpdateMessage(Object p);
string getName();
}
class database
{
public string username = "username";
private string name = "user details";
private string grade = "user grade";
public string getName(Object o)
{
if (o is Staff) { return name; }
else { return "Go away!"; }
}
public string getgrade() { return grade; }
}
public class Gateway
{
public void DoSomethingWithPerson(IPerson person)
{
string iD = person.getName();
if (person is Student)
{
return "go away!";
}
else if (person is Staff)
{
return name;
}
}
}
This is a somewhat convoluted question. So, first off, I'd like to point out a few style issues with your C#.
Your database class is lowercase while the rest are cased consistently. Some methods are inconsistent (for example, you use idiomatic PascalCase for some methods, and camelCase or lowercase for others).
IPerson actually has no purpose here because you can pass instances of Staff and Student around as a Person and use everything in basically the same way as now. In most cases, you'll want to choose either an interface or an abstract base class, not both.
C# has a notion of "properties", which is basically a convenient syntax for getters and setters. This is preferred to public fields (as in public string username in your database class or your public string id in Person) because it allows you to keep the implementation of the backing field private. The syntax for this is public string username { get; set; } if you just want a default implementation. You can expand this to more complicated things. For example, maybe you want to ensure that the username is trimmed. (1)
Minor nitpick, but typically object with lowercase o is used.
You don't actually have to call .ToString() on objects in string formatting interpolation. (2)
(1)
private string m_username;
public string username {
get { return m_username; }
set { m_username = (value != null ? value.Trim() : value); }
}
(2) These lines are equivalent.
Console.WriteLine(id + " notified that {1}", id, o.ToString());
Console.WriteLine("{0} notified that {1}", id, o);
Now on to the problem. To me, it sounds like you want different behavior for different classes. With the way it's phrased, this sounds like an access/permissions issue. Depending on how your data store is set up (in this case, it looks like constants in the code, but you could easily do some kind of query), you could do something like...
[Flags]
public enum Permission {
None = 0,
GetName = 1
}
public abstract class Person {
/* ... */
public abstract Permission Permissions { get; }
}
public class Staff : Person {
/* ... */
public override Permission Permissions {
get { return Permission.GetName; }
}
}
public class Student : Person {
/* ... */
public override Permission Permissions {
get { return Permission.None; }
}
}
public class Database {
/* ... */
private Dictionary<string, string> NamesDatabase { get; set; }
public string getName(string id) {
// As a consequence of being managed by Gateway, assume that the caller has access
return NamesDatabase[id];
}
}
public class Gateway {
public string DoSomethingWithPerson(Person person, string desiredNamePersonId) {
if (person.Permissions.HasFlag(Permission.GetName)) {
Database db = new Database();
return db.getName(desiredNamePersonId);
}
return "go away!";
}
}
Supposing we have a constructor for Database as such:
public Database() {
NamesDatabase = new Dictionary<string, string>(2);
NamesDatabase["id1"] = "Student Amy";
NamesDatabase["id2"] = "Staff Mary";
}
And a Main as such:
static void Main() {
Gateway gate = new Gateway();
Console.WriteLine("Student id1 looks up Staff id2: {0}", gate.DoSomethingWithPerson(new Student("id1"), "id2"));
Console.WriteLine("Staff id2 looks up Student id1: {0}", gate.DoSomethingWithPerson(new Staff("id2"), "id1"));
Console.ReadLine();
}
The output is:
Student id1 looks up Staff id2: go away!
Staff id2 looks up Student id1: Student Amy
Feel free to ask clarifying questions if any part is unclear or I'm way off the mark in my assessment.
i'm not sure if this is what you need.
static void Main(string[] args)
{
var gateway = new Gateway();
Console.WriteLine(gateway.DoSomethingWithPerson(new Staff(1)));
Console.WriteLine(gateway.DoSomethingWithPerson(new Student(1)));
}
public class Staff : Person
{
public Staff() { }
public Staff(int id) : base(id) { }
public override void Update(object o)
{
Console.WriteLine(ID + " notified that {1}", ID, o);
}
public override void UpdateMessage(object p)
{
Console.WriteLine(ID + " notified about new message in chat: {1}", ID, p);
}
public override string GetName()
{
return DataBase.GetName(ID);
}
}
public class Student : Person
{
public Student() { }
public Student(int id) : base(id) { }
public override void Update(object o)
{
Console.WriteLine(ID + " notified that {1}", ID, o);
}
public override void UpdateMessage(object p)
{
Console.WriteLine("Message for " + ID + " {1}", ID, p);
}
public override string GetName()
{
return "Go Away!";
}
}
public abstract class Person : IPerson
{
public int ID;
protected Person() { DataBase = new DataBase(); }
public abstract string GetName();
protected Person(int i) { ID = i; DataBase = new DataBase(); }
public abstract void Update(Object o);
public abstract void UpdateMessage(Object p);
public DataBase DataBase { get; set; }
}
public interface IPerson
{
void Update(Object o);
void UpdateMessage(Object p);
string GetName();
}
public class DataBase
{
public string USERNAME = "username";
private const string Name = "user details";
private const string Grade = "user grade";
public string GetName(int id)
{
// you should perform get something.
return Name;
}
public string GetGrade() { return Grade; }
}
//maybe call it facade
public class Gateway
{
public string DoSomethingWithPerson(IPerson person)
{
return person.GetName();
}
}
I'll show a problem by example. There is a base class with fluent interface:
class FluentPerson
{
private string _FirstName = String.Empty;
private string _LastName = String.Empty;
public FluentPerson WithFirstName(string firstName)
{
_FirstName = firstName;
return this;
}
public FluentPerson WithLastName(string lastName)
{
_LastName = lastName;
return this;
}
public override string ToString()
{
return String.Format("First name: {0} last name: {1}", _FirstName, _LastName);
}
}
and a child class:
class FluentCustomer : FluentPerson
{
private long _Id;
private string _AccountNumber = String.Empty;
public FluentCustomer WithAccountNumber(string accountNumber)
{
_AccountNumber = accountNumber;
return this;
}
public FluentCustomer WithId(long id)
{
_Id = id;
return this;
}
public override string ToString()
{
return base.ToString() + String.Format(" account number: {0} id: {1}", _AccountNumber, _Id);
}
}
The problem is that when you call customer.WithAccountNumber("000").WithFirstName("John").WithLastName("Smith") you can't add .WithId(123) in the end because return type of the WithLastName() method is FluentPerson (not FluentCustomer).
How this problem usually solved?
Try to use some Extension methods.
static class FluentManager
{
public static T WithFirstName<T>(this T person, string firstName) where T : FluentPerson
{
person.FirstName = firstName;
return person;
}
public static T WithId<T>(this T customer, long id) where T : FluentCustomer
{
customer.ID = id;
return customer;
}
}
class FluentPerson
{
public string FirstName { private get; set; }
public string LastName { private get; set; }
public override string ToString()
{
return string.Format("First name: {0} last name: {1}", FirstName, LastName);
}
}
class FluentCustomer : FluentPerson
{
public long ID { private get; set; }
public long AccountNumber { private get; set; }
public override string ToString()
{
return base.ToString() + string.Format(" account number: {0} id: {1}", AccountNumber, ID);
}
}
after you can use like
new FluentCustomer().WithId(22).WithFirstName("dfd").WithId(32);
You can use generics to achieve that.
public class FluentPerson<T>
where T : FluentPerson<T>
{
public T WithFirstName(string firstName)
{
// ...
return (T)this;
}
public T WithLastName(string lastName)
{
// ...
return (T)this;
}
}
public class FluentCustomer : FluentPerson<FluentCustomer>
{
public FluentCustomer WithAccountNumber(string accountNumber)
{
// ...
return this;
}
}
And now:
var customer = new FluentCustomer()
.WithAccountNumber("123")
.WithFirstName("Abc")
.WithLastName("Def")
.ToString();
A solution where you need fluent interface, inheritance and also some generics...
Anyhow as I stated before: this is the only option if you want to use inheritance and access also protected members...
public class GridEx<TC, T> where TC : GridEx<TC, T>
{
public TC Build(T type)
{
return (TC) this;
}
}
public class GridExEx : GridEx<GridExEx, int>
{
}
class Program
{
static void Main(string[] args)
{
new GridExEx().Build(1);
}
}
Logically you need to configure stuff from most specific (customer) to least specific (person) or otherwise it is even hard to read it despite the fluent interface. Following this rule in most cases you won't need get into trouble. If however for any reason you still need to mix it you can use intermediate emphasizing statements like
static class Customers
{
public static Customer AsCustomer(this Person person)
{
return (Customer)person;
}
}
customer.WIthLastName("Bob").AsCustomer().WithId(10);
public class FluentPerson
{
private string _FirstName = String.Empty;
private string _LastName = String.Empty;
public FluentPerson WithFirstName(string firstName)
{
_FirstName = firstName;
return this;
}
public FluentPerson WithLastName(string lastName)
{
_LastName = lastName;
return this;
}
public override string ToString()
{
return String.Format("First name: {0} last name: {1}", _FirstName, _LastName);
}
}
public class FluentCustomer
{
private string _AccountNumber = String.Empty;
private string _id = String.Empty;
FluentPerson objPers=new FluentPerson();
public FluentCustomer WithAccountNumber(string accountNumber)
{
_AccountNumber = accountNumber;
return this;
}
public FluentCustomer WithId(string id)
{
_id = id;
return this;
}
public FluentCustomer WithFirstName(string firstName)
{
objPers.WithFirstName(firstName);
return this;
}
public FluentCustomer WithLastName(string lastName)
{
objPers.WithLastName(lastName);
return this;
}
public override string ToString()
{
return objPers.ToString() + String.Format(" account number: {0}", _AccountNumber);
}
}
And invoke it using
var ss = new FluentCustomer().WithAccountNumber("111").WithFirstName("ram").WithLastName("v").WithId("444").ToString();
Is a fluent interface really the best call here, or would an initializer be better?
var p = new Person{
LastName = "Smith",
FirstName = "John"
};
var c = new Customer{
LastName = "Smith",
FirstName = "John",
AccountNumber = "000",
ID = "123"
};
Unlike a fluent interface, this works fine without inherited methods giving back the base class and messing up the chain. When you inherit a property, the caller really shouldn't care whether FirstName was first implemented in Person or Customer or Object.
I find this more readable as well, whether on one line or multiple, and you don't have to go through the trouble of providing fluent self-decorating functions that correspond with each property.
I know this is now an old question, but I wanted to share my thoughts about this with you.
What about separating fluency, which is a kind of mechanism, and your classes, when you can ? This would leave your classes pure.
What about something like this ?
The classes
public class Person
{
public string FirstName { get; set; }
public string LastName {get; set;}
public override string ToString()
{
return $"First name: {FirstName} last name: {LastName}";
}
}
public class Customer : Person
{
public string AccountNumber { get; set; }
public long Id { get; set; }
public override string ToString()
{
return base.ToString() + $" account number: {AccountNumber} id: {Id}");
}
}
A class that adds some fluent mechanism
public class FluentCustomer
{
private Customer Customer { get; }
public FluentCustomer() : this(new Customer())
{
}
private FluentCustomer(Customer customer)
{
Customer = customer;
}
public FluentCustomer WithAccountNumber(string accountNumber)
{
Customer.AccountNumber = accountNumber;
return this;
}
public FluentCustomer WithId(long id)
{
Customer.Id = id;
return this;
}
public FluentCustomer WithFirstName(string firstName)
{
Customer.FirstName = firstName;
return this;
}
public FluentCustomer WithLastName(string lastName)
{
Customer.LastName = lastName;
return this;
}
public static implicit operator Customer(FluentCustomer fc)
{
return fc.Customer;
}
public static implicit operator FluentCustomer(Customer customer)
{
return new FluentCustomer(customer);
}
}
An extension method to switch to fluent mode
public static class CustomerExtensions
{
public static FluentCustomer Fluent(this Customer customer)
{
return customer;
}
}
The same example as in question
Customer customer = new Customer().Fluent()
.WithAccountNumber("000")
.WithFirstName("John")
.WithLastName("Smith")
.WithId(123);