Использование объектов в разных методах - PullRequest
1 голос
/ 22 декабря 2008

Редактировать снова: Я думаю, я понял это сейчас. Все, что мне нужно сделать - это использовать текущий двоеточие класса, к которому я хочу получить доступ? Человек: студент или человек: учитель Это правильно?

В настоящее время я пытаюсь изучить все тонкости объектно-ориентированного программирования. В настоящее время у меня есть новый объект, который выглядит примерно так:

class student
{
    int grade; //0 - 100 as opposed to the characters A, B, C, etc.
    string teacher; //For the teacher of the class the student is in.

}

class teacher
{ 
    int courseAverage;
    string name; 
    //teacher.name would correspond to the teacher in the student class.
}

class Program
{
    student Jim;
    Jim = new student();
    teacher John;
    John = new teacher();
}

static void grades()
{
    Jim.grade = 100;
}

static void teacher()
{
    Jim.teacher = "John Smith";
}

static void average()
{
    int average; //For the sake of simplicity I'll leave the average at an int.
    average = (Jim.grade + Sue.grade + Sally.grade + Robert.grade) / 4;
    /*A loop would be set before the average variable to 
    ensure that only students of John would be counted in this.*/

}

static void teacheraverage()
{
    John.courseAverage = average;//from the average method.
}

EDIT:

Что я хотел бы сделать, это изменить информацию из другого класса. Тем не менее, я хотел бы изменить информацию от ученика Джима в методе из класса программы. Метод для вычисления среднего балла для студентов, у которых есть данный учитель.

Кроме того, единственная причина, по которой я использую static в них, заключается в том, что это единственный способ, которым мне удалось получить доступ к переменным в разных методах. Я пытался использовать статические методы для использования методов в разных классах, но безуспешно. Есть ли другой способ сделать это?

Я бы хотел использовать ученика Джима несколькими способами. Один, который установит оценку Джима, и другой, который установит учителя. Я хотел бы использовать различные методы в этом случае, чтобы я мог узнать, как это делается.

Хорошо, похоже, мое понимание неверно. Я собираюсь попробовать методы в рамках подхода класса.

Ответы [ 7 ]

5 голосов
/ 22 декабря 2008

Поскольку вы используете C # и предполагаете, что используете .NET 3.5, ваш класс, вероятно, будет выглядеть примерно так:

public class Student
{
    public int Grade { get; set; }
    public string Teacher { get; set; }
}

Grade и Teacher - это автоматические свойства, которые примерно эквивалентны методам получения и установки в Java. Свойства в C # по сути являются ярлыками для получения и установки локальных членов класса.

Ваше использование вышеупомянутого класса будет выглядеть примерно так:

public class Program
{
    // creates a new Student object with the properties Grade and Teacher set.
    Student s = new Student() { Grade = 100, Teacher = "John Smith" }

    Console.Write(s.Grade); // outputs 100
    Console.Write(s.Teacher); // outputs John Smith
}

Это то, что вы ищете?

3 голосов
/ 22 декабря 2008

Ну, как минимум, тремя способами.

  1. Оценка оценок и методы преподавания в классе ученика:

public class Student
{
    int grade; //0 - 100 as opposed to the characters A, B, C, etc.
    string teacher; //For the teacher of the class the student is in.

    public void SetGrades()
    {
        grade = 100;
    }

    public void SetTeacher()
    {
        teacher = "John Smith";
    }
}

class Program
{
    public static void Main()
    {
        Student Jim;
        Jim = new Student();
        Jim.SetTeacher();
        Jim.SetGrades();
    }
}

или 2. Перевести студента к методам:


class Program
{
    public static void Main()
    {
        Student Jim;
        Jim = new Student();
        grades(Jim);
        teacher(Jim);
    }

    static void grades(Student student)
    {
        student.grade = 100;
    }

    static void teacher(Student student)
    {
        student.teacher = "John Smith";
    }
}

или 3. Используйте Jim как переменную в классе Program, чтобы вам не приходилось передавать его чему-либо


class Program
{
    static Student Jim;

    public static void Main()
    {
        Jim = new Student();
        grades();
        teacher();
    }

    static void grades()
    {
        Jim.grade = 100;
    }

    static void teacher()
    {
        Jim.teacher = "John Smith";
    }
}

Обратите внимание, что во всех примерах я указывал, что класс Student имеет имя S в верхнем регистре, чтобы отличать его от параметра и любых локальных переменных, которые у вас могут быть.

Важно знать различия.

В первом решении вы просите сам объект установить оценки и учителя. Если вы выполняете эти операции часто, они, вероятно, принадлежат самому классу, а не являются операциями снаружи.

Во втором решении вы передаете ученика. Это позволяет легко работать с несколькими учащимися, поскольку код не привязан к работе с одним объектом.

В третьем решении вам не нужно ничего передавать, но ваш код теперь заблокирован для работы только с одним студентом за раз, в поле Jim.

Лично я бы разработал вариант первого решения, только немного более гибкий с точки зрения того, какую оценку он будет устанавливать и какого учителя. Вероятно, используя свойства (которые вы также должны посмотреть больше.)

1 голос
/ 23 декабря 2008

Вы все еще упускаете важный момент: класс связывает данные с его методами. Таким образом, метод, который устанавливает учителя Джима, является частью класса Student, как и метод, который устанавливает оценку Джима.

Сначала подумайте об этом на естественном языке. «Джим - студент; у учеников есть имена, строгие идентификационные номера и классы. В классах есть учителя и классы. Студенты получают оценки по каждому классу в конце семестра».

Итак, у нас есть ученик класса. Студент, когда вы создаете объект из него, нуждается в имени студента и идентификаторе студента, поэтому «конструктор» должен быть чем-то со строкой имени и идентификатором студента - также назовите его String - чтобы инициализировать его. Я не знаю C #, поэтому я сделаю псевдокод с фигурными скобками ...

class Student {
    String name;
    String studentID;
    Course crsList = List<Course>; // "list of courses."
    Student(String name, String studentID ){
        // Make a new student, the "constructor"
        this.name = name;
        this.studentID = studentID;
    }
    addCourse(Course c){
        // Add a course to the student's list
        this.crsList.append(c); // Adds c to end of crsList
    }
}

Здесь написано: «У ученика есть имя и идентификатор, и мы можем добавить классы в их коллекцию классов».

class Teacher {
    String name;
    Course crsList = List<Course>;
    Teacher(String name){
        this.name = name;
    }
    // ... more methods here.
}

Но мы видим, что учителя и ученики - это люди разных типов, поэтому мы «рефакторинг» это, чтобы собрать общую часть

class Person {
    String name;
    Person(String name){
        this.name = name;
    }
    // ... more methods
}

Теперь мы меняем Учителя и Ученика, поэтому мы говорим

class Student : Person {
    String studentID;
    Student(String name, String studentID){
        // Now we need to initialize the Person part
        super(name);
        // and the special Student part
        this.studentID = studentID;
    }
}

, который теперь говорит, что «Студент - это тот человек, у которого есть дополнительный идентификатор студента, и к которому мы можем добавлять занятия».

Вы продолжите определять «addClass» для Teach, , но как часть класса Teacher . Зачем? Потому что добавление класса для учителя означает нечто иное, чем добавление класса для ученика. Вы добавили бы метод к Студенту, который берет Курс и Оценку, находит Курс и назначает ему оценку как-то. (Тест на популярность: является частью курса или частью студента?)

1 голос
/ 22 декабря 2008

lassevk отлично справляется с , отвечая на ваш вопрос - в основном, как вы получаете доступ к экземпляру Student с именем Jim несколькими способами.

Хотелось бы отметить, что вы делаете здесь процедурный код. Не то, чтобы с этим обязательно что-то было не так - просто вы действительно не «получаете» ОО здесь.

Быстрый, 2-минутный пример оригинального пути:

class Student {
   public string Name { get; private set; }

   public Student(string name) {
      if (string.IsNullOrEmpty(name)) throw new ArgumentException();
      this.Name = name;
   }
}

class Teacher {
   public string Name { get; private set; }

   public List<Course> Courses { get; private set; }

   public Grade GetAverageCourseGrade() {
       int totalCourseGrade;
       foreach (Course course in this.Courses) {
          totalCourseGrade += course.GetAverageGrade().Value;
       }
       return new Grade(totalCourseGrade / this.Courses.Count);
   }

   public Teacher(string name) {
       if (string.IsNullOrEmpty(name)) throw new ArgumentException();
       this.Name = name;
       this.Courses = new List<Course>();
   }
}

class Course {
   public string Name { get; private set; }

   public IEnumerable<Student, Grade> StudentGrades { get; private set; }

   public Grade GetAverageGrade() {
      int totalGrade;
      // could use LINQ, but I'll make it slightly more explicit
      foreach (KeyValuePair<Student, Grade> studentGrade in this.StudentGrades) {
         Grade grade = kvp.Value;
         totalGrade += grade.Value;
      }
      return new Grade(totalGrade / this.StudentGrades.Count());
   }

   public Course(string name) {
       if (string.IsNullOrEmpty(name)) throw new ArgumentException();
       this.Name = name;
       this.StudentGrades = new Dictionary<Student, Grade>();
   }
}

class Grade {
   public int Value { get; private set; }

   public char Letter { 
       get {
          switch (this.Value / 10) {
             case 10: case 9:
               return 'A';
             case 8:
               return 'B';
             case 7:
               return 'C';
             case 6:
               return 'D';
             default:
               return 'F';
          }
       }
   }

   public Grade(int value) {
      if (value < 0 || value > 100) throw new ArgumentOutOfRangeException();
      this.Value = value;
   }
}

class Program {
   static int Main(string[] args) {
      Teacher john = new Teacher("John Smith");

      Course cs101 = new Course("Computer Science 101");
      john.Courses.Add(cs101);

      Student mark = new Student("Mark Brackett");
      Student xesaniel = new Student("Xesaniel");

      cs101.Students.Add(mark, new Grade(90));
      cs101.Students.Add(xesaniel, new Grade(95));

      Console.WriteLine(john.GetAverageCourseGrade());
   }
}

Там много церемоний и шума, но важный момент заключается в том, что Учитель и Курс знают, как рассчитать свои собственные средние оценки и проверить / применить свое собственное внутреннее состояние. Метод Main в действительности отвечает только за координацию настройки и любых взаимодействий между классами.

Технически, многие отношения здесь являются двунаправленными - например, у учителя много курсов, и у курса есть один учитель. Но двунаправленные отношения могут быть PITA для управления - и здесь нет веских причин для этого.

0 голосов
/ 22 декабря 2008

Попытайтесь представить класс как шаблон для создания машины. Объект - это машина. Когда вы используете его, вам все равно, как оно работает внутри. Вы просто используете различные рычаги и переключатели снаружи, чтобы управлять им, и светодиоды, которые сообщают вам ответы, и так далее. Это «черный ящик» для вас.

Рычаги и переключатели - это методы и свойства. Они предоставляют «пользовательский интерфейс» для взаимодействия с объектом.

Код внутри методов является внутренним. Как это работает - секрет . Это делает объект более простым в использовании (если он хорошо спроектирован). Поля, которые в конечном итоге хранят информацию, также являются секретами. К ним нет прямого доступа из кода вне методов класса.

public class Student
{
    // Notice how these details are private
    private List<Subjects> _subjects = new List<Subjects>();
    private DateTime _started;

    // A property that only has a 'getter' because the value shouldn't be modified
    public DateTime Started
    {
        get { return _started; }
    }

    // Methods carry out actions. This one calls on to a method in another object.
    public void Enroll(Subject s)
    {
        if (_subjects.Contains(s))
            throw new Exception("Already studying that course");

        s.RegisterStudent(this);
        _subjects.Add(s); 
    }

    public void Flunk(Subject s)
    {
        if (!_subjects.Contains(s))
            throw new Exception("Can't flunk that subject, not studying it");

        s.RemoveStudent(this);
        _subjects.Remove(s);
    }
}

Если вы следуете этому подходу, вы на пути к ориентации объекта. У вас еще есть много интересных вещей для изучения - безопасность исключений, злоупотребление наследованием, слабая связь ...

0 голосов
/ 22 декабря 2008

Ваша модель упрощена и не указана. Но давайте пока проигнорируем это; -)

в приведенных ниже примерах я также игнорирую детали свойств и обозначаю конструкторы, чтобы не перепутать главную проблему моделирования

Ученик и Учитель оба люди (как указали Чарли Мартин и другие)

//people have names
public class Person
{
    public Person(string _name)
    {
        Name = _name;
    }
    public string Name;
}

Ученик - это человек, у которого есть класс и учитель

//students are people with a grade and a teacher
public class Student : Person
{
    public Student(string _name, int _grade, 
        Teacher _teacher) : base(_name)
    {
        Grade = _grade;
        Teacher = _teacher;
        Teacher.Students.Add(this);  //add to the teacher's collection
    }
    public int Grade;
    public Teacher Teacher;
}

Учителя - это люди со средней оценкой курса и набором учеников.

public class Teacher : Person
{
    public Teacher(string _name) : base(_name)
    {
    }
    public int CourseAverage;
    public IList<Student> Students = new List<Student>();
    public void ComputeAverageGrade()
    {
        int sum = 0;
        foreach(Student s in Students)
        {
            sum += s.Grade;
        }
        CourseAverage = sum / Students.Count;
    }
}

В вашем примере у вас есть несколько учеников, и вы подсчитываете средний балл

public class Program
{
    public static void Main(string [] args)
    {
        Teacher JohnSmith = new Teacher("John Smith");

        Student Jim = new Student("Jim",100,JohnSmith);
        Student Sue = new Student("Sue",90,JohnSmith);
        Student Sally = new Student("Sally",70,JohnSmith);
        Student Robert = new Student("Robert",100,JohnSmith);

        //add our resident overachiever
        Student JonSkeet = new Student("Jon Skeet",150,JohnSmith);

        JohnSmith.ComputeAverageGrade();

        Console.WriteLine("Course Average for " + JohnSmith.Name + " is " +
            JohnSmith.CourseAverage.ToString());
    }
}

В более реалистичной модели каждый учащийся, скорее всего, будет проходить более одного курса, и каждый учитель, вероятно, будет преподавать более одного курса, поэтому вам нужно будет смоделировать курсы. Курсы существуют только в течение семестра или квартала и т. Д.

0 голосов
/ 22 декабря 2008

Хорошо, здесь есть основное недоразумение. Ваши методы связаны с классом. То, что у вас есть, это в основном структуры с некоторыми функциями, которые их используют; не ошибаюсь, но не ОО вообще.

То, что вы действительно хотите, это что-то вроде этого (в, надеюсь, хороший пояснительный псевдокод):

class Person
  name : String
  Person(namearg: String) -- your constructor
    name = namearg;
  end
end

class Student :: Person -- read :: as "is a kind of"
  Student(namearg : String)
    super(namearg) -- calls the Person ctor
  end
  -- more stuff will go in here
end
-- Teacher looks much the same

class Course
  courseName : String
  teacher : Teacher
  students : list of Student
  Course(namearg : string)
    courseName = namearg 
  end
  addStudent(s : student)
    students.append(s) -- add student to the end of the list
  end
  -- and so on.
end

Дело в том, что класс знает все, что нужно знать о том, что он описывает: и данные, которые он использует, и операции, которые можно выполнить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...