0

Events を継承する Leisure クラスからプロパティにアクセスしたときに、Events クラス内のプライベート変数 'name' が変更されない理由について疑問に思っています。プロパティを使用して変更するには Leisure が必要です。フォーム クラスでは、イベントから「名前」の値を読み取ることができるはずです。下記参照:

public partial class Form1 : Form //Main form class
{
    private string eventType; //used for event type selection
    private string formEventName; //used to store selected event name


     private void itemSend_Click(object sender, EventArgs e)
    {
        //encapsulation
        Events myEv = new Events();
        string name=itemInput.Text; 
        myEv.myEvent(eventType, name);
        formEventName = myEv.myName;
        txtOutput.Text = "Event name is " + formEventName + "\r\n";            
    }

class Events:Form1
{
    private string name; //private variable for event name      
     public string myName //used to change property value depending on what eveny type/ event name
    {
        get { return name; }
        set { name = value; }   
    }
    public void myEvent(string eventType, string eventName) //variable recieved from main form class
    {
        if (eventType == "Leisure")
        {

           Leisure myLes = new Leisure(); 
           myLes.eventNames(eventName);  

        }
        else
        {
            //test for other event types
        }  
    }

    class Leisure:Events
 {
    public void eventNames(string eventName) 
    {

        //when adding new items add one with a capital and one without
        myEventNames.Add("music");
        myEventNames.Add("Music");
        if (myEventNames.Contains(eventName))
        {
            myName = eventName;
        }
        else
        {
            MessageBox.Show("item not found, please try again"); //error message
        }
    }
  }
4

4 に答える 4

2

Eventsから継承するのは間違っているようですForm1

と言うとnew Events()、既存のフォームとは関係のない新しいオブジェクトが取得され、それに加えた変更は既存のフォームに影響を与えません。あなたが言うとき、それは再び起こりますnew Leisure()

于 2012-12-18T15:10:09.710 に答える
2

使用myNameしているプロパティはname、ItemSend_Click で作成された myEv インスタンスの name プライベート フィールドではなく、myLes インスタンスのプライベート フィールドを変更します。

オブジェクト指向言語では、クラスのインスタンスを作成すると、そのインスタンスには、クラスで宣言されたすべての非静的プライベート/パブリック変数のコピーが含まれます。だからあなたが書くとき

   Leisure myLes = new Leisure(); 

Leisure クラスのインスタンスを作成していますが、このインスタンスは Events から継承していますが、内部変数のセットが異なり、現在の Event インスタンス (myEv) と同じ変数ではありません。

あなたのコードを見て、私はと呼ばれる3番目のクラスを作成することをお勧めします

public class EventFactory
{
    public Event CreateEvent(string eventType, string eventName)
    {
        switch(enventType)
        {
            case "Leisure":
                 Leisure myLes = new Leisure(); 
                 myLes.eventNames(eventName);  
                 return myLes;
            // case Add other specialized events here:
            // break;
            default:
                 return null;
        }
    }
}

Form1 からの継承を削除して Events クラスを変更し (私が知る限り必要ありません)、メソッド myEvent を変更します。

あなたの ItemSend_Click はこのように書くことができます

private void itemSend_Click(object sender, EventArgs e)
{
    Events myEv = new EventFactory().CreateEvent(eventType, itemInput.Text);
    formEventName = myEv.myName;
    txtOutput.Text = "Event name is " + formEventName + "\r\n";            
}

これは、からLeisure派生しEvents、すべての Leisure インスタンスを Event インスタンスとして扱うことができるため、機能します。

于 2012-12-18T15:09:27.330 に答える
1

myNameフィールドのmyLes (Leisure)変数を変更するだけなのでmyEv、 myEv.myName はまだ空です。

于 2012-12-18T15:09:49.917 に答える
0

したがって、あなたが抱えている問題は、あなたのコードの主要な根本的な問題のほんの小さな兆候であり、あなたが続けるにつれて現れ続けるだけです.

あなたがやろうとしていることについて、より伝統的に見られているものとより一致するものにあなたが持っているものを書き直しました。完璧ではありません。一度に多くのことを投げかけないように、物事をかなりシンプルに保つように努めました。

public partial class Form1 : Form //Main form class
{
    private TextBox itemInput;
    private TextBox txtOutput;
    private string eventType; //used for event type selection
    private string formEventName; //used to store selected event name

    private void itemSend_Click(object sender, EventArgs e)
    {
        string name = itemInput.Text;
        try
        {
            Event myEvent = Event.Create(eventType, name);
            txtOutput.Text = "Event name is " + myEvent.Name + "\r\n";
        }
        catch (ArgumentException ex)//if the event name isn't valid
        {
            MessageBox.Show(ex.Message);
        }
    }
}

public abstract class Event
{
    public string Name { get; private set; }
    public Event(string eventName)
    {
        Name = eventName;
    }
    public static Event Create(string eventType, string eventName)
    {
        if (eventType == "Leisure")
        {

            Leisure myLes = new Leisure(eventName);
            return myLes;

        }
        //  else if { ... } test for other event types
        else
        {
            return null;
        }
    }
}

public class Leisure : Event
{
    private static List<string> myEventNames =
        new List<string>() { "music", "Music" };
    public Leisure(string eventName)
        : base(eventName)
    {
        if (!myEventNames.Contains(eventName))
        {
            throw new ArgumentException("Not a valid Leisure event name");
        }
    }
}

それでは、いくつかの変更点について見ていきましょう。まず、Eventから継承しませんForm1。そうすべきではありません。イベントは、概念的にはフォームのタイプではなく、特定のタイプのフォームは言うまでもありません。Eventは、継承だけでなく、いかなる形式の知識も持ってはなりません。使用するのは他のクラスですForm1が、他のタイプのクラス、フォームなどでも同じように簡単に使用できます。

Eventから継承しないことに加えてForm、抽象化しました。抽象メソッドはありません。プレーンなだけを作成するEventべきではなく、特定のタイプのイベントのみを実際に作成する必要があります。共通の基本クラスであるため、偶発的な作成を防ぎ、読みやすさを向上させるのに最も簡単abstractです。

私もEvent不変にしました。名前をいつでも変更できるようにして、名前を付けずにイベントを作成し、後で変更するのではなく、イベントを作成する前に名前とタイプを指定する必要があるように構成しました。作成後に変更することです。はコンストラクターで設定され、ロジックが適切なサブタイプを選択して実際に作成するためNameの静的メソッドを追加しました。「ファクトリーパターン」の簡易版です。通常、型を文字列として渡さないことに注意してください。のようなものにして、有効なオプションが何であるかを簡単に判断できるようにします。CreateEventEnum

今にLeisure。論理的には、Leisure実際には であり、Eventそれを継承する必要があります。あなたの問題は、 のインスタンスと のインスタンスを作成し、それらが同じ変数を共有していると仮定したという事実に起因していEventましLeisureた。そうではありませんが、 のインスタンスを持つことができなくなったので、その混乱はなくなるはずですEvent

が作成されるLeisureと、基本クラス コンストラクターを使用してNameを設定します。これは、プロパティ自体を設定するアクセス権がないためです。

私が見ることができるmyEventNamesのは、有効な名前の単なるリストであり、異なるタイプのLeisureインスタンス間で変化するようには見えないため、 であることが理にかなっていますstatic。つまり、すべてのインスタンス間で共有され、一度だけ作成されます。

また、型のコンストラクターMessageBoxから呼び出しを移動しました。Leisure代わりに、例外をスローしています。ここでの主な考え方は、UI コードとビジネス コードを混在させてはならないということです。 EventLeisureはどちらもビジネス オブジェクトであり、UI が存在する場合、その内容について何も認識すべきではありません。コンソール アプリ、ASP アプリケーションなどからそれらを使用できる必要があります。その上、これは無効な名前であり、型が存在してはならないということなので、最終結果はコンストラクターで Excpetion をスローすると、オブジェクトが「有効」になることはありません。とにかくオブジェクトを使用し続けることを許可するのではなく、存在してはならないオブジェクトの作成を許可しません。

その例外は のtry/catchブロックで捕捉され、イベントの作成に失敗したことに基づいて Form1適切な例外が表示されます。MessageBox

于 2012-12-18T15:43:27.153 に答える