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");
Related
I have two classes, i want to put instances of a class Bear in a list from class Cave like below, but that code doesn't works. Should classes be in relationship? How can I change code?
class Bear
{
public Bear(int age, string name)
{
this.Age = age;
this.Name = name;
}
}
class Cave
{
List<Bear> cave = new List<Bear>();
cave.Add(new Bear(16, "Johnny"));
cave.Add(new Bear(10,"Herman"));
}
If you are getting any errors, please post them. You can't put code like that directly in the class. All executable code must be inside a method. Move the code in your Cave class into a method:
class Bear
{
public int Age { get; set; }
public string Name { get; set; }
public Bear(int age, string name)
{
this.Age = age;
this.Name = name;
}
}
class Cave
{
List<Bear> cave = new List<Bear>();
public Cave()
{
cave.Add(new Bear(16, "Johnny"));
cave.Add(new Bear(10,"Herman"));
}
}
I have a question about the following code.
First, these codes worked well.
However, there is no declaration only defined about “courses” in class Student.If in the Constructor of Student the argument is constant, will these code be safe?
Thanks for helping!:)
public class Student
{
public string name;
public int age;
public string[] courses;
public Student(string _name, int _age,params string[] _courses)
{
name = _name;
age = _age;
courses = _courses;//is this OK if _courses is constant?
}
}
public class work : MonoBehaviour
{
void Start()
{
/*
string[] courses={"math", "English"};
Student Tom = new Student("Tom",18,courses);
//It's wrong!
*/
Student Tom = new Student("Tom", 18, "math", "English");
string Tom_text = JsonUtility.ToJson(Tom);
Debug.Log(Tom_text);
}
}
The way you have it, anyone can change the Student object at anytime.
If you do not want anyone changing anything about the Student object once it has been created, then make it immutable like this:
public class Student
{
public string Name { get; private set; }
public int Age { get; private set; }
public IEnumerable<string> Courses { get; private set; }
public Student(string name, int age, params string[] courses)
{
this.Name = name;
this.Age = age;
this.Courses = courses;
}
}
Now people cannot change the the properties because the setters are private.
And to follow the .NET naming convention, do not use - underscores in parameter names and use Pascal Notation for property names. I have removed the underscores and used Pascal Notation for property names.
EDIT
#diemaus mentioned a good point in the comments to this answer, in C# 6:
You can actually remove the private set entirely, and just leave it { get; }. This is allowed as long as long as you only set the properties in the constructor.
I have four classes :
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Product> Product { get; set; }
}
public class Product
{
public int ProductNumber { get; set; }
public string ProductColor { get; set; }
}
///////////////////////////////////////////////
public class Customer_
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Article> Article { get; set; }
}
public class Article
{
public int ArticleNumber { get; set; }
public string ArticleColor { get; set; }
}
And one instance :
var Cus = new List<Customer>
{
new Customer()
{
FirstName = "FirstName1",
LastName = "LastName1",
Product = new List<Product>
{
new Product()
{
ProductColor = "ProductColor1",
ProductNumber = 11
}
}
},
new Customer()
{
FirstName = "FirstName2",
LastName = "LastName2",
Product = new List<Product>
{
new Product()
{
ProductColor = "ProductColor2",
ProductNumber = 12
}
}
}
};
I want to create a new object List<Customer_> with the value of my instance Cus. For example Customer.FirstName = Customer_.FirstName, Customer.Product.ProductColor = Customer_.Article.ArticleColor etc
What is the best way to do this easily, could one use a Dictionary?
Mapping can be accomplished through the use of an Interface.
Define an interface(s) which provide a mapping of logically named properties such as the common color properties you mention:
// Some entities have different named properties but can be joined
// using those properties. This interface shows a common color which
// when implemented will route the processing to a common shared property
// which reports and sets the associated color.
public interface IDefinedColor
{
string Color { get; set; }
}
If you have to create partial classes for Product and Article and have them adhere to said interfaces. Hint if using an entity mapper such as EF this is a great way to do such maping using partials. Implement implement the interface and hook up the commonality:
// Holds the common properties for future processing.
public partial class Product : IDefinedColor
{
public string Color
{
get { return ProductColor; }
set { ProductColor = value; }
}
}
Then work off of the IDefinedColor mapped implementations as needed.
By using interfaces one is letting all future developers know of the contract which specifies a business logic equality in the properties and it is not hidden in other joining classes.
You could create a mapper extension class
public static class MapperExtension
{
public Customer_ Convert(this Customer customer)
{
return new Customer_()
{
FirstName = customer.FirstName,
LastName = customer.LastName,
Article = customer.Product.Convert()
};
}
public static List<Article> Convert(this List<Product> products)
{
return products.Select(x=> new Article(){
ArticleNumber = x.ProductNumber,
ArticleColor = x.ProductColor
};
}
}
make sure you reference the proper namespace where you place the extension class.
Call the code like this
Where customers is a List filled from your code
List<Customer_> convertedCustomers_ = customers.Select(x=> x.Convert()).ToList();
It depends on the relationhip between those components but I would simply add constructor to Customer_ that accepts a Customer object. And then you invoke that do perform the conversion. e.g.
public class Article
{
public Article(Product source)
{
this.ArticleNumber = source.ProductNumber;
this.ArticleColor = source.ProductColor;
}
}
public class Customer_
{
public Customer_(Customer source)
{
this.FirstName = source.FirstName;
this.LastName = source.LastName;
this.Article = source.Product.Select(o => new Article(o)).ToList()
}
...
}
//and finally to convert the list you can do something like
//initial list
var Cus = new List<Customer>() { ... etc. }
/converted list
var Cus_ = Cus.Select(o => new Cusomter_(o)).ToList();
Edit: I see from your comment above that you actually have 100 properties to map. I can see this is a pain. But if you have complex transformations like Product to Article then I would still go the manual route as above so you can be completely clear about what is going on. Alternatively you could look to use inheritance to redesign your objects with common base classes or interfaces, that would probably make mapping easier.
I am making a console test with C#.
Actually I have never used of C# but VB.Net. I want to create arrays for one-to-many relationship.
My one is 'A Student' has 'Name','Sex',...,'Courses Taken'.
A Student would take many course, each course has a Title and Included Subject. Each subject has Name, Description and Point.
Like this.
Student
- Name - Sex - Courses Taken
Take Courses
- Course Title - Subject Included
Subject
- Subject Name [Math] [MVC]
- Subject description [Advance] [Building Website]
- Subject Point [6.9] [5.6]
I want to store each entity in Arrays but I don't know how to connect subjects/courses to each Students. And how can I get Student who attending Math or MVC. Because every students can have more then more course/ more than one subjects.
You'll want to create classes to describe your different objects.
class Student
{
string Name { get; set; }
Gender Sex { get; set; } // write an enum for this
IEnumerable<Course> CoursesTaken { get; set; }
}
class Course
{
string Title { get; set; }
Subject Subject { get; set; }
}
class Subject
{
string Name { get; set; }
string Description { get; set; }
double Points { get; set; }
}
Using List to create enumerations of instances of these new types allow you to use LINQ to select or evaluate members of the list (nested for loops work as well):
// populate a list of students called studentList
//...
// use LINQ to select the students you want
var mathResults = studentList.Where(student => student.CoursesTaken.Any(course => course.Subject.Name == "Math"));
I feel like I've done with it in good way...
Pls check my code for my ques! ^^
I first made 3 classes as below..
class Students
{
public string StudentName;
public int StudSize;
public bool StudSex;
public List<Take_Courses> tcourses;
public Students() { }
public Students(string name, int size, bool sex, List<Take_Courses> tcourses)
{
StudentName = name;
StudSize = size;
StudSex = sex;
this.tcourses = tcourses;
}
}
and
class Take_Courses
{
public string classname;
public List<Arr_Courses> arr_Course;
public Take_Courses() { }
public Take_Courses(string classname, List<Arr_Courses> arr_courses)
{
this.classname = classname;
arr_Course = arr_courses;
}
}
class Arr_Courses
{
public string cosname;
public string cosdesc;
public float cospoint;
public Arr_Courses() { }
public Arr_Courses(string name, string description, float point)
{
cosname = name;
cosdesc = description;
cospoint = point;
}
}
I then initialized values in Main class as below;
Arr_Courses acos=new Arr_Courses();
Arr_Courses acos1=new Arr_Courses("Math","Advance Math1",9.5f);
Take_Courses cos=new Take_Courses();
Take_Courses cos_take1=new Take_Courses("Info Tech",new List<Arr_Courses>{acos1});
Students stu=new Students();
Students Stu1 = new Students("Milla", 22, true,new List<Take_Courses>{cos_take1});
I then make another List to be generated names of student and use for looping and assign each one to List.
I think some important part is this.
if (arr_stud[i].tcourses[j].arr_Course[k].cosname.Equals("Math"))
{
Math_Stud++;
MathStudents[i] = arr_stud[i];
}
I am sharing this if anyone needs something like this. Any ungraded codes is appreciated to be shared. Thanks so so.
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;
}
}