1

もう一度編集:私は今それを手に入れたと思います。私がする必要があるのは、アクセスできるようにしたいクラスの現在のクラスコロンを使用することだけですか? Person : 学生、または Person : 教師でよろしいですか。

私は現在、オブジェクト指向プログラミングのインとアウトを学ぼうとしています。現在、次のような新しいオブジェクトがあります。

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.
}

編集:

私がやりたいことは、別のクラスからの情報を変更することです。ただし、プログラム クラス内のメソッドでジムの生徒からの情報を変更したいと考えています。指定された教師がいる生徒の成績の平均を計算するメソッド。

また、これらで static を使用する唯一の理由は、それがメソッド間で変数にアクセスできた唯一の方法だからです。クラス全体でメソッドを使用するために静的メソッドを使用しようとしましたが、成功しませんでした。これを行う別の方法はありますか?

ジムの学生を複数の方法で使用したいと思います。1 つはジムの成績を設定し、もう 1 つは教師を設定します。この場合、さまざまな方法を使用して、それがどのように行われるかを学びたいと思います。

わかりました、私の理解が正しくなかったようです。クラスアプローチ内のメソッドを試してみます。

4

7 に答える 7

5

C#を使用していて、.NET 3.5を使用していると仮定すると、クラスはおそらく次のようになります。

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

GradeとTeacherは自動プロパティであり、Javaのgetterおよびsetterとほぼ同等であり、メソッドになります。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
}

これはあなたが探しているものですか?

于 2008-12-22T00:34:07.193 に答える
3

まあ、少なくとも3つの方法。

  1. Student クラスの成績と教師のメソッドを作成します。

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 を付けて、パラメーターやローカル変数と区別していることに注意してください。

違いを知ることが重要です。

最初の解決策では、オブジェクト自体に成績と教師を設定するように依頼します。これらの操作が頻繁に行われる場合は、外部の操作ではなく、クラス自体に属している可能性があります。

2 番目の解決策では、学生を迂回させます。これにより、コードが単一のオブジェクトを操作するように配線されていないため、複数の学生と簡単に連携できます。

3 番目のソリューションでは、何も渡す必要はありませんが、コードは Jim フィールドで一度に 1 人の学生だけを操作するようにロックされます。

個人的には、最初の解決策のバリエーションを考え出しますが、設定する学年と教師の点でもう少し柔軟です。おそらくプロパティを使用しています(これについても詳しく調べる必要があります)。

于 2008-12-22T00:28:54.317 に答える
1

lassevkは、質問に適切に答えます。つまり、基本的に、複数のメソッドでJimという名前のStudentインスタンスにアクセスするにはどうすればよいですか。

ただし、ここで手続き型コードを実行していることを指摘しておきます。それには必ずしも何か問題があるわけではありません。ただ、ここでOOを実際に「取得」していないというだけです。

OOっぽい方法の簡単な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メソッドは、実際には、セットアップとクラス間の相互作用の調整のみを担当します。

技術的には、ここでの関係の多くは双方向です。たとえば、教師には多くのコースがあり、コースには1人の教師がいます。しかし、双方向の関係は管理するPITAになる可能性があり、ここでは説得力のある理由はありません。

于 2008-12-22T02:02:17.610 に答える
1

クラスはデータをそのメソッドに関連付けます。 したがって、Jim の先生を設定するメソッドは、Jim の成績を設定するメソッドと同様に、Student クラスの一部です。

まず自然言語で考えてください。「ジムは学生です。学生には名前、学籍番号、クラスがあります。クラスには教師と教室があります。学生は学期末に各クラスの成績を受け取ります。」

クラス Student があります。学生は、そこからオブジェクトを作成するときに学生の名前と学生 ID を必要とするため、「コンストラクター」は名前文字列と学生 ID (文字列とも呼びます) を持つものである必要があり、それを初期化します。私は 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
    }
}

これは、「生徒には名前と ID があり、クラスのコレクションにクラスを追加できる」ことを示しています。

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
}

ここで、Teacher と Student を変更して、次のように言います。

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;
    }
}

これは、「学生は、追加の学生 ID を持ち、クラスを追加できる一種の人物です」と述べています。

Teach の "addClass" を定義しますが、Teacher クラスの一部として定義します。なんで?教師のためにクラスを追加することは、生徒のためにクラスを追加することとは異なる意味を持つためです。Course と Grade を取得し、Course を見つけて何らかの方法で彼に Grade を割り当てるメソッドを Student に追加します。(簡単なクイズ: 学年はコースの一部ですか、それとも学生の一部ですか?)

于 2008-12-23T20:27:58.797 に答える
0

モデルが単純化されすぎて、指定が不十分です。しかし、今のところそれを無視しましょう;-)

以下の例では、主要なモデリングの問題を混乱させないように、プロパティの詳細を無視し、コンストラクターをスタブ化しています。

学生と教師は両方とも人です(チャーリー・マーティンと他の人が指摘したように)

//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());
    }
}

より現実的なモデルでは、各学生が複数のコースを受講する可能性が高く、各教師が複数のコースを教える可能性があるため、コースをモデル化する必要があります。コースは、学期または四半期などの期間にのみ存在します。

于 2008-12-22T02:04:35.467 に答える
0

さて、ここに基本的な誤解があります。 メソッドはクラスに関連付けられています。 あなたが持っているのは基本的にそれらを使用するいくつかの関数を備えた構造体です。間違いではありませんが、OOではありません。

あなたが本当に欲しいのはこのようなものです(うまくいけば良い説明の擬似コードで):

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

重要なのは、クラスは、クラスが説明することについて知っておくべきこと、つまり、使用するデータと実行できる操作の両方をすべて知っているということです。

于 2008-12-22T00:37:07.250 に答える
0

クラスを機械を作るための設計図と考えてみてください。オブジェクトは機械です。使っているときは、中の動きは気にしません。外側のさまざまなレバーやスイッチを使用して制御し、LED で答えを教えてくれます。それはあなたにとって「ブラックボックス」です。

レバーとスイッチはメソッドとプロパティです。これらは、オブジェクトと対話するための「ユーザー インターフェイス」を公開します。

メソッド内のコードは内部です。仕組みは秘密です。これにより、オブジェクトが使いやすくなります (適切に設計されている場合)。最終的に情報を格納するフィールドもシークレットです。クラスのメソッド外のコードから直接アクセスされることはありません。

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);
    }
}

このアプローチに従えば、オブジェクト指向への道を歩んでいることになります。例外の安全性、継承の乱用、疎結合など、学ぶべき楽しいことはまだたくさんあります。

于 2008-12-22T02:06:01.470 に答える