There are two classes Person and Employee
when it mapped to c# code
public class Person
{
private string Name;
}
public class Employee : Person
{
private string Department;
public string GetName()
{
return "Person Name";
}
}
My question is where can i write the getters and setters for this private attributes.is it ok to write them with in the same Person and Employee classes if yes isn't there a problem with mapping? because methods are also with in the same class(GetName()) or do i have to use separate classes for writing getters and setters.i'm confused with this class diagram mapping with the code.Can any one resolve this for me??
Firstly, I would recommend you to you the properties approach and not the getters / setters one.
My take:
public class Person {
private string name;
public string Name {
get {
return this.name;
}
}
}
public class Department {
private int id;
private string name;
public int ID {
get {
return this.id;
}
}
public string Name {
get {
return this.name;
}
}
}
public class Employee : Person {
private Department department;
public Department Department {
get {
return this.department;
}
}
}
Employee.Name returns the employee name which is being declared within the Person class.
Related
Firstly I'd like to say that I truly sorry if this is an idiotic question but I just started learning about Classes and I've thought that I managed to understand it but this confused the heck outta me so seems like I didn't
I'm doing this C# OOP edx course where I had to make 5 classes (student, teacher, UProgram, degree, course) in different class files and there's this task:
Instantiate a UProgram object called Information Technology.
Instantiate a Degree object, such as Bachelor, insude the UProgram object.
Instantiate a Course object called softeng inside the Degree object.
Was done, (hopefully) no issues with that one
and 3. - eh.
How I was thinking (bear in mind, im a beginner so):
First I've thought of nested classes but I wasn't really sure about how they work and didn't think I could put the classes in different files as they should be nested (?)
And then I tried something with the constructor but I couldn't see how I could make it work
So now my final try was to create methods inside the classes (except for the Teacher and Student one as they won't have anything ""belonging to them"" like a Course has students and teachers belonging to it
So I have the method in the form of (- let's say we're in the Degree class, having a method for creating several Courses for this degree -):
public void Newcourse(string Cname, Course sth)
{
sth = new Course();
sth = Cname;
}
And before I can use it, I have to write the
Course softeng = new Course();
line aka make an instance of the Course class before I can do the 3. point of the task
The whole code:
UProgram.cs
public class UProgram
{
public void Newdegree(string Dname, Degree sth)
{
sth = new Degree();
sth.Dname = Dname;
}
}
Degree.cs
public class Degree : UProgram
{
public string Dname { get; set; }
public void Newcourse(string Cname, Course sth)
{
sth = new Course();
sth.Cname = Cname;
}
}
Course.cs
public class Course : Degree
{
public void NewTeacher(string FirstName, string LastName, Teacher sth)
{
sth = new Teacher();
sth.FirstName = FirstName;
sth.LastName = LastName;
}
public void NewStudent(string FirstName, string LastName, Student sth)
{
sth = new Student();
sth.FirstName = FirstName;
sth.LastName = LastName;
}
public string Cname { get; set; }
}
Teacher.cs
public class Teacher : Course
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Student.cs
public class Student : Course
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Program.cs
class Program
{
static void Main(string[] args)
{
var Information_Technology = new UProgram();
Degree bachelors = new Degree();
Information_Technology.Newdegree("Bachelors", bachelors);
Course softeng = new Course();
bachelors.Newcourse("Software Engineering", softeng);
Teacher t1 = new Teacher();
softeng.NewTeacher("Colin", "Firth", t1);
Student s1 = new Student();
softeng.NewStudent("Mary", "Sue", s1);
Student s2 = new Student();
softeng.NewStudent("Joseph", "Jojo", s2);
Console.ReadLine();
}
}
I know-I know, it's very convoluted and I'm not even sure whether this is good or not but that was all I could come up with and I'd be very grateful if any of you could help me out (in a tone that won't make me cry)
Thank you and again, sorry for this mess of a code, eh, i tried
The wording does seem a bit strange, but I believe they are simply saying that this class should contain a property of the type it is meant to "contain", and instantiate it in the constructor. For example:
public class Degree
{
public Course Course { get; set; }
public Degree()
{
Course = new Course();
}
}
public class Course
{
public Student Student { get; set; }
public Course()
{
Student = new Student();
}
}
public class Student
{
public Student()
{
}
}
Upon creating a an instance of Degree, it will create an instance of a Course inside it, which will create an instance of a Student inside it. Thus Degree contains a Course which contains a Student.
The example above is using the constructors to instantiate these but as they are public properties they could also just be created from outside it (in which case the constructors above are unnecessary):
var degree = new Degree();
degree.Course = new Course();
degree.Course.Student = new Student();
Just a few comments:
I have big doubts that you need any inheritance here. For example: Student : Course - I doubt that "Student is a Course" :) . So, you probably need some composition here. I don't know (and can't remember) what diamonds in your picture exactly means, but can guess that filled diamond - is one item (or at least one, not sure) and empty means many items.
So, here how I would do this (you can split each class to separate file):
public class UProgram
{
public string Name { get; set; }
public Degree Degree { get; set; }
public UProgram(string name, Degree degree)
{
Name = name;
Degree = degree;
}
}
public class Degree
{
public string Name { get; set; }
public Course Course { get; set; }
public Degree(string name, Course course)
{
Name = name;
Course = course;
}
}
public class Course
{
public List<Teacher> Teachers { get; set; }
public List<Student> Students { get; set; }
public string Name { get; set; }
public Course(string name, List<Teacher> teachers, List<Student> students)
{
Name = name;
Teachers = teachers;
Students = students;
}
}
public class Teacher
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
and Main function:
static void Main(string[] args)
{
var teachers = new List<Teacher>
{
new Teacher
{
FirstName = "Colin",
LastName = "Firth"
}
};
var students = new List<Student>
{
new Student
{
FirstName = "Mary",
LastName = "Sue"
},
new Student
{
FirstName = "Joseph",
LastName = "Jojo"
}
};
var softEngCourse = new Course("Software Engineering", teachers, students);
var bachelorDegree = new Degree("Bachelor", softEngCourse);
var technologyProgram = new UProgram("Technology", bachelorDegree);
Console.ReadLine();
}
I still not sure that this exactly what your course is expected from you, this is how I would write code like this (with some minor changes, but it doesn't matter here).
Why in that way? Because it is almost always better to build an object in a "working" state when it explicitly receives everything that it needs, rather than create a raw object that will start in "invalid" state. Secondly, it is usually better to not "bake in" parameters values inside, but give a class consumer (I mean "developer" here) to configure it.
You are misunderstanding the task. Course should not inherit from Degree, since Course is not a Degree. Instead, you will need to define Course data member in your Degree class. Neither Student, nor Teacher is a Course, therefore you should not inherit them from Course. They are members.
I assume that a Degree can be achieved by a single Course.
I assume that a Course has a single Teacher.
I assume that a Course can have multiple Students.
This means that you have a Person class, like this, since both Student and Teacher is a Person:
public class Person {
protected String firstName;
protected String lastName;
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public Student(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
Now, inherit Teacher from Person:
public class Teacher : Person {
public Teacher(String firstName, String lastName) : base(firstName, lastName) {
}
}
and Student:
public class Student : Person {
public Student(String firstName, String lastName) : base(firstName, lastName) {
}
}
Now, let's define Course:
public class Course {
protected Teacher teacher;
protected List<Student> students;
protected String name;
public String getName() {
return this.name;
}
public Teacher getTeacher() {
return this.teacher;
}
public List<Student> getStudents() {
return this.students;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public void setTeacher(String firstName, String lastName) {
this.teacher = new Teacher(firstName, lastName);
}
public void addStudent(Student student) {
this.students.Add(student);
}
public void addStudent(String firstName, String lastName) {
this.students.Add(new Student(firstName, lastName));
}
public Course(String name) {
this.name = name;
this.students = new List<Student>();
}
}
Now, let's define Degree:
public class Degree {
protected String name;
protected Course course;
public String getName() {
return this.name;
}
public Course getCourse() {
return this.course;
}
public void setCourse(Course course) {
this.course = course;
}
public void setCourse(String name) {
this.course = new Course(name);
}
public Degree(String name) {
this.name = name;
}
}
Now, this is how you achieve what you wanted:
Degree degree = new Degree("mydegree");
degree.setCourse("myCourse");
Course course = degree.getCourse();
course.setTeacher("John", "Smith");
course.addStudent("James", "Doe");
I have an interface with a read only property
public interface IPerson
{
string Name { get; }
}
and a concrete class...
public class Person : IPerson
{
public Person()
{
Name = "Person";
}
public string Name
{
get
{
return Name;
}
}
}
I want Name to be read only externally to this class, but how do I set it from within the concrete class?
Error: Person.Name cannot be assigned to.
How do I set the value of this property from within Person class?
This doesn't have anything to do with the interface, you're just declaring the property incorrectly. In C# 6, you can create a read-only property like this:
public class Person : IPerson
{
public Person()
{
Name = "Person";
}
public string Name { get; }
}
In earlier versions, you can use a read-only backing field which you can set:
public class Person : IPerson
{
private readonly string _name;
public Person()
{
_name = "Person";
}
public string Name
{
get { return _name; }
}
}
Note that the interface only requires the property has a getter, the implementation doesn't have to be read-only. You could add a setter if you had reason to modify the value:
public class Person : IPerson
{
public Person()
{
Name = "Person";
}
public string Name { get; set; }
}
The setter could be private if you only needed to be able to change the value from within the class.
You can use a private property to hold the value.
public class Person : IPerson
{
private string _name;
public Person()
{
_name = "Person";
}
public string Name
{
get
{
return _name;
}
}
}
Right now, you're trying to read the property by reading the property. Needless to say, this will result in an endless loop. Instead, you either need to use full-blown auto-properties, or a manual backing field.
public class Person : IPerson
{
public Person()
{
Name = "Person";
}
public string Name { get; private set; }
}
You simply have a private setter (pre c#6):
public class Person : IPerson
{
public Person()
{
Name = "Person";
}
public string Name { get; private set; }
}
Try using accessors:
private string _name;
public string Name
{
get
{
return _name;
}
}
You can then set the value of _name inside any method or the constructor.
I want Name to be read only externally to this class, but how do I set it from within the concrete class
First of all, let's realize that: an interface only describes a set of public requirements; it does not prevent us from implementing other public members, nor does it limit our ability to create private members.
Therefore, to make a property writeable from inside the class but read-only elsewhere, we can declare the set method with private scope:
public class Person : IPerson
{
// Name is read-only outside the class, but can be set internally
public string Name { get; private set; } = "DefaultName";
public Person() { }
public Person(string name)
{
// Potentially do some validation before setting the name
if (!IsValidName(name))
throw new ArgumentException("Name cannot be null, empty, or whitespace.");
Name = name;
}
private bool IsValidName(string name)
{
return !string.IsNullOrWhitespace(name);
}
// Continued below...
And if we want to, we can give access to the private setter through a method. This is often done in order to make the renaming of a person very intentional (for example, it prevents accidental assignments when a comparison was intended). The client will get a design-time error from the compiler if they try person.Name = "Foo"; but they can write person.RenameAs("Foo");
public void RenameAs(string newName)
{
// Potentially do some validation before setting the name
if (IsValidName(newName)) Name = newName;
}
}
Given a tree hierarchy, suppose it is the following:
abstract class Person : ICloneable
...
sealed class Student : Person
...
I want to implement the ICloneable interface. In the Student.Clone method I wish to do something like:
{
Student clonedStudent = base.Clone() as Student;
clonedStudent.x1 = this.x1;
return clonedStudent
}
Because Person is abstract I can't create a Person in the Person.Clone() method, so I can't return a cloned Person, so I can't clone a Person.
The best answer I have figured out is to overload the Clone() method in the Person class to receive a Person, clone and return it. Then in the Student.Clone implementation call this overload to clone the person's related fields.
Something like this:
//In the Person class:
public abstract object Clone();
protected Person Clone(Person clonedPerson)
{
// Clone all person's fields
return clonedPerson:
}
//In the Student class:
public override object Clone()
{
Student clonedStudent = base.Clone(new Student()) as Student;
// Clone all student's fields
return clonedStudent
}
Of course if any of the above class required to build any logic in its constructors this solution is more than useless. Any idea to implement a better one?
I think this is a subproblem of a more general one, so the answer will fit very well into a large superset.
Since your Student class inherits the properties/fields from the base class (Person), it is not necessary to clone the person object.
The solution is to not implement the Clone() method within the abstract base class, but instead make it abstract and force the implementation in any sub-classes which inherit from it. In order to clone, you can simply instantiate a new instance of the Student class and populate the base properties using a clone constructor. See my example. I'm not sure if this helps in any way.
class Program
{
static void Main(string[] args)
{
Student studentA = new Student(1000, "Defense Against the Dark Arts", "Harry", "Potter", 25);
Student studentB = (Student)studentA.Clone();
}
}
public abstract class Person : ICloneable
{
public string FirstName { get; set; }
public string Surname { get; set; }
private int SomePrivateVariable { get; set; }
public Person()
{
}
public Person(string firstName, string surname, int privateVariableDefault)
{
this.FirstName = firstName;
this.Surname = surname;
this.SomePrivateVariable = privateVariableDefault;
}
public Person(Person original)
{
this.FirstName = original.FirstName;
this.Surname = original.Surname;
this.SomePrivateVariable = original.SomePrivateVariable;
}
public abstract object Clone();
}
public sealed class Student : Person
{
public int StudentId { get; set; }
public string CourseTitle { get; set; }
public Student()
{
}
//Constructor with all the fields, passed down to the base class
public Student(int studentId, string courseTitle, string firstName, string surname, int baseVariableDefault)
: base(firstName, surname, baseVariableDefault)
{
this.StudentId = studentId;
this.CourseTitle = courseTitle;
}
//A clone constructor which takes an object of the same type and populates internal
//and base properties during construction
public Student(Student original)
: base(original)
{
this.FirstName = original.FirstName;
this.Surname = original.Surname;
this.StudentId = original.StudentId;
this.CourseTitle = original.CourseTitle;
}
public override object Clone()
{
Student clone = new Student(this);
return clone;
}
}
I have a two classes.This is my code:
//My Base class
public class People
{
public People()
{
}
protected string name;
protected string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
}
//The Child class
public class Student:People
{
private int id;
public Student()
{
}
public Student (int id, string name)
{
this.id = id;
this.Name = name;
}
public int ID
{
get
{
return this.id;
}
set
{
this.id = value;
}
}
}
When i create instance of the Student class like the one below i can't access the NAME property from the parent class People.
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
Student student1 = new Student();
student1. // only ID property is accessible
}
}
Do i make something wrong? Since Students is child class of People i expected that the NAME property should be accessible trough the Student instances.Thank you very much for the help in advance.
You're not doing anything wrong, but if you want to access
Name
via an instance of
Student
You have to declare that property public. Otherwise, only access from within that class is allowed (not via an instance).
You are still accessing it Outside the class so it would need to be public.
You can read about access modifiers here:
http://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx
Change your properties to:
public string Name {get;set;}
And you should be good to go.
The Student class does not expose the Name property to the outside.
If you would derive a class from student, you could access the Name property.
Alternatively, you could reimplement Name using the new keyword like this:
public class Student : People
{
private int id;
public new String Name { get; set;}
public Student()
{
}
public Student(int id, string name)
{
this.id = id;
this.Name = name;
}
public int ID
{
get
{
return this.id;
}
set
{
this.id = value;
}
}
}
you should make your Properties public
//My Base class
public class People
{
public People()
{
}
protected string name;
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
}
You can not access protected property of base class using instance of a derived class.
Protected property if a property that can be accessed only within bounds of derived types.
If you need to access to that property from instance of the Student, declare it like a public inside its base class: People.
If you also need in some way override its behavior, can declare it public virtual in base class and override it in Student
I believe your problem is that your protected fields are in the base class not the inherited class. Look at this: http://msdn.microsoft.com/en-us/library/bcd5672a.aspx
public class BaseClass
{
public string foo
}
public class SubClass
{
protected string bar
}
This is a more common use of protected.
what are the advantages of calling one constructor by other if there are multiple constructors?
Thanks
You don't repeat yourself.
A change in implementing one constructor also affects all the other constructors, instantly.
Copy and Pasting code is bad and should be avoided.
the same advantages you get when you do method overloading : you don't repeat the same code
public class Person
{
public Person(string name,string lastName )
{
Name = name;
LastName = lastName;
}
public Person(string name, string lastName,string address):this(name,lastName)
{
//you don't need to set again Name and Last Name
//as you can call the other constructor that does the job
Address = Address;
}
public string Name { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
}
Looking at the already posted answers i will just they that you always walk the way from the default constructor down to the most specialized constructor. Trying to do the same the other way around always leads to code duplications or problems:
The good way:
public class Foo()
{
public Foo()
: this(String.Empty)
{ }
public Foo(string lastName)
: this(lastName, String.Empty)
{ }
public Foo(string lastName, string firstName)
: this(lastName, firstName, 0)
{ }
public Foo(string lastName, string firstName, int age)
{
LastName = lastName;
FirstName = firstName;
Age = age;
_SomeInternalState = new InternalState();
}
}
The bad way:
public class Foo()
{
public Foo(string lastName, string firstName, int age)
: this(lastName, firstName)
{
Age = age;
}
public Foo(string lastName, string firstName)
: this(lastName)
{
FirstName = firstName;
}
public Foo(string lastName)
: this()
{
LastName = lastName;
}
public Foo()
{
_SomeInternalState = new InternalState();
}
}
The problem of the second example is that the part what to do with all the parameters is now cluttered over all constructors, instead implemented in just one (the most specialized). Just imagine you like to derive from this class. In the second example you have to override all constructors. In the first example you only have to override the most specialized constructor to get full control over every constructor.
If you want to pass default values to a base constructor.
public class YourClass
{
private int SomeInt;
public YourClass() : this(0)
{
// other possible logic
}
public YourClass(int SomeNumber)
{
SomeInt = SomeNumber;
}
}
This follows the DRY principle (Don't Repeat Yourself). A simple example, but it should illustrate the idea.
I used it when I want to pass default or null values to the other constructors. In the case above the user does not have to pass null when calling the constructor-- they can call it with nothing.
public class Widget(){
public Widget() : this(null){
}
public Widget(IRepository rep){
this.repository = rep;
}
}