4
package cen.col.course.demo;

import java.io.Serializable;

public class Course implements Serializable {

private static final long serialVersionUID = 1L;
protected String code;
protected String title;
protected Professor professor;

public Course( String code) throws InvalidDataException {
    super();
    setCode(code);
}

public Course(String code, String title ) throws InvalidDataException  {
    this(code);
    setTitle(title);
}

public Course(String code, String title, Professor professor) throws InvalidDataException   {
    this(code,title);
    setProfessor(professor);
}
    public String getCode() {
    return code;
    }

protected void setCode(String code) throws InvalidDataException {
    if ( code == null || code.length() < 1) {
        throw new InvalidDataException("Course must have a course code");
    }
    this.code = code;
}

public String getTitle() {
    return title;
}

public void setTitle(String title)  throws InvalidDataException {
    if ( title == null || title.length() < 1) {
        throw new InvalidDataException("Course must have a title");
    }
    this.title = title;
}

public Professor getProfessor() {
    return professor;
}

public void setProfessor(Professor professor) {
    this.professor = professor;
}

public String toString() {
    String output = getCode() + ": [" + getTitle() + "]";
    if (getProfessor() != null ) {
        output += " is taught by " + getProfessor();
    }
    return output;
}

public boolean equals(Course c) {
    if ( ! this.getCode().equals(c.getCode())){
        return false;
    }
    if ( ! this.getTitle().equals(c.getTitle())){
        return false;
    } 
    // should the prof field be included in test for equality?
    if ( ! this.getProfessor().equals(c.getProfessor())){
        return false;
    } 
    return true;
}


}

3 つの質問があります。

  1. 教授がコンストラクターからセッター メソッドを呼び出していることに気付きました。私は少し調べてみましたが、それについてはさまざまな考えがありました。大丈夫だと言う人もいれば、サブクラスを使用するときに注意する必要があると言う人もいます。コンストラクターからセッターを呼び出しても大丈夫ですか?

  2. 彼女はコンストラクターからセッターを呼び出しているため、コンストラクターは例外をスローします。私の質問は、コンストラクターからセッターを呼び出すことが安全な方法ではない場合、それを行う適切な方法は何ですか? 私の推測では、引数のないコンストラクターを宣言し、セッターを使用してオブジェクトを構築します。

  3. 私はこれを行うと思いますが、問題外ですか?

    Course createCourse = new Course("1234","プログラミング 1","パム ハルパート");

私は 3 つの引数を取るコンストラクターを呼び出していますが、コンストラクターからセッターを呼び出すことが安全でない場合、どのようにこれを行い、例外を設定しますか? if ステートメントを使用できますか? 何かが空白かどうかを確認し、必要に応じて例外をスローしますか?

4

4 に答える 4

1
  1. コンストラクター内でセッターを呼び出すと、一般に、セッターが既に内部にいくつかの検証ロジックを持っている場合があり (例の setTitle など)、このロジックを複製したくないという利点があります。ただし、セッターを呼び出すと、既に述べたように、サブクラスが予期しない動作でそれらをオーバーライドする可能性があるという問題が発生する可能性があります。これを解決するには、setter を private または final にして、オーバーライドできないようにします。プライベート/ファイナル セッターのみを呼び出すことは良い方法であり、問​​題が発生することはありません。

  2. 無効なデータを取得するコンストラクターが例外をスローしても問題ありません。無効なオブジェクトを作成したくありません。

  3. 最初に (空のコンストラクターを介して) 空のオブジェクトを作成し、次にセッターを介してそのデータを埋めることは、かなり悪い習慣です。このようにすると、しばらくの間、オブジェクトが無意味な状態になり、一部のデータが埋められ、一部のデータが埋められず、問題が発生する可能性があります。また、すでに述べた別の回答として、コンストラクターの数を減らすことを検討する必要があります-教授のいないコースは本当に有効ですか? そうでない場合、そのようなオブジェクトを作成するコンストラクターは必要ありません...

于 2012-09-21T15:23:26.487 に答える
0

セッターの呼び出しは、セッターが何らかの形式のデータ検証を行う場合に役立ちます。これにより、検証を 1 か所に配置して、インスタンス化の時点で設定されたプロパティが検証規則に準拠していることを確認できます。

ただし、これに関する問題は、サブクラスがこれらのセッターをオーバーライドする可能性があることです。つまり、期待される検証が行われなくなります。

そのため、検証を行うプライベートセッターを作成することは理にかなっています。コンストラクターでこれらのプライベート セッターを呼び出します。パブリック セッターも必要な場合は、プライベート セッターの周りにパブリック ラッパー セッターを作成するだけでかまいません。


サイドノート:

あなたの教授の例は少しずれています。

検証は、常に設定されているtitleことを確認するように設計されているようです。ただし、このコードには、 を設定できないcodeコンストラクターも用意されています。これはほぼ確実にバグです (コード レビューで間違いなくフラグを立てます)。title

于 2012-09-21T15:18:02.110 に答える
0

これは宿題か何かの勉強なので、教授はきっとあなたに何かを見せたがるでしょう。

でも 、
Course createCourse = new Course("1234","Programming 1","Pam Halpert");

実際に行うのが最善です。

何を開発しているかにもよりますが、ほとんどの場合、プログラミング言語を設計している場合を除き、できるだけ少ないコンストラクターを提供したいと考えています。パブリック API または製品に取り組んでいる場合、消費者がバグを作成することを許可する場合、消費者が間違いを犯したり、API を悪用したりしないようにする必要があります。

コンストラクターは例外をスローできます。これは良いことです。

私が見る限り、セッターの理由を呼び出すことは、いくつかの検証またはいくつかのロジックを実行していました。これは問題ありません。

コンストラクターで作業を行うことは、悪い習慣と見なされることに注意してください。

クラスの外でそれを行い、それらをコンストラクター引数またはセッター/ゲッターとして渡す必要があります。

于 2012-09-21T15:15:50.783 に答える
0

個人的に私はセッターの大ファンではありません。私は不変性が好きなので、あなたの例ではパラメーターを ctor に渡します。そこでチェックを行ってから、最終フィールドに割り当てます。セッターは存在しません。ゲッターしかありません。

更新したい場合は、コピー コンストラクターを導入できます。

そうすれば、オブジェクトが構築された時点で、そのオブジェクトが有効な状態にあることがわかります。その一部が null の場合、コンストラクターをオーバーロードできます。引数なしのコンストラクターとセッターを使用することで、どのフィールドに入力する必要があるかわかりません。コンストラクターのパラメーターで強制することにより、オブジェクトを有効な状態で強制的に初期化します。

于 2012-09-21T15:17:17.223 に答える