0

我想知道为什么当我从继承自 Event 的 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

myName您正在使用的属性更改namemyLes 实例的私有字段,而不是在 ItemSend_Click 中创建的 myEv 实例的名称私有字段。

在面向对象语言中,当您创建类的实例时,该实例具有该类中声明的每个非静态私有/公共变量的副本。所以当你写

   Leisure myLes = new Leisure(); 

您正在创建 Leisure 类的实例,但此实例虽然从 Events 继承,但具有一组不同的内部变量,而不是当前 Event 实例 (myEv) 的相同变量。

查看您的代码,我建议创建一个名为

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

更改您的 Events 类,删除 Form1 的继承(据我所知不需要)和方法 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 回答
2

Events继承自似乎是错误的Form1

当您说 时new Events(),您将获得一个与现有表单无关的新对象,并且您对其所做的任何更改都不会影响现有表单。当您说 时,这种情况再次发生new Leisure()

于 2012-12-18T15:10:09.710 回答
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. 它不应该这样做。事件在概念上根本不是一种形式,更不用说那种特定类型的形式了。AnEvent不应该以任何方式了解任何形式,而不仅仅是继承。它只是Form1将使用的其他一些类,但它可以很容易地被任何其他类型的类、表单或其他类型使用。

除了Event不继承之外Form,我还把它抽象化了。它没有任何抽象方法,只是你不应该只创建一个 plain Event,你应该只实际创建某种特定类型的事件。作为一个通用基类,最简单的方法是防止意外创建并通过将abstract.

我也做了Event不可变的。而不是允许随时更改名称,创建一个事件而不给它一个名称,然后再更改它,我已经将它配置为你需要在创建事件之前提供名称和类型,然后就没有办法了一旦它被创建就改变它。在Name构造函数中设置,我添加了一个静态Create方法,逻辑可以在其中选择正确的子类型Event并实际创建它。这是“工厂模式”的简单版本。请注意,通常我不会将类型作为字符串传递。我会把它做成一个类似的东西Enum,这样更容易分辨出有效的选项是什么。

现在进入Leisure. 从逻辑上讲,Leisure真的是一个Event并且应该从它继承。您的问题源于您创建了 的实例Event,以及 的实例Leisure,并假设它们共享相同的变量。他们没有,但既然你永远无法拥有Event.

创建a 时Leisure,它使用基类构造函数来设置Name,因为它无权设置属性本身。

从我所看到myEventNames的只是一个有效名称的列表,它似乎在不同类型的Leisure实例之间没有变化,所以它是有意义的static,这意味着它在所有实例之间共享并且只创建一次。

我还将MessageBox调用移出Leisure类型的构造函数。相反,我抛出了一个异常。这里的主要思想是您不应该将您的 UI 代码与您的业务代码混合在一起。 Event并且Leisure都是业务对象,不应该知道任何关于 UI 存在的信息(如果有的话)。您应该能够从控制台应用程序、ASP 应用程序等中使用它们。最重要的是,因为我们要说的是这是一个无效的名称并且该类型不应该存在,所以最终结果是在构造函数中抛出 Excpetion 是该对象永远不会变为“有效”。我们不允许创建不应该存在的对象,而不是允许他们继续使用该对象。

该异常被 中的try/catch块捕获,它根据创建事件的失败 Form1显示适当的。MessageBox

于 2012-12-18T15:43:27.153 回答