繁体   English   中英

设计不好? 使用抽象类集合来包含具体的孩子

[英]Bad Design? Use Abstract Class Collection to Include Concrete Children

我想在我正在编写的最新Web应用程序中正确探索/理解抽象类的实现。 但是,虽然我可以用具体类的值实例化一个抽象类令人惊讶,但我想知道这是否不是一种好方法,因为我似乎无法在儿童具体课程。

我设法创建了一个包含两个具体孩子的IList的IEnumerable基类集合。 虽然具体子级共享相同的类型,但我的想法是在需要时在网页中调用具体子级属性。 当然,我觉得这种设计并不是实现目标的真正方法。

抽象类的类:

 public abstract class MasterTicket
    {
        public Guid id{ get; set; }
        public DateTime openTime{ get; set; }
        public DateTime closeTime{ get; set; }
        public bool active{ get; set; }
        public string summary{ get; set; }
        public string description{ get; set; }
        public DateTime updateTime{ get; set; }
        //TODO: Create foreign key relationship to user model
        public Guid userUpdateId{ get; set; }
        //TODO: Create foreign key relationship for tickets from other systems
        public Guid externalAppId{ get; set; }
        //TODO: Create foreign key relationship to user model
        public Guid userOpenId{ get; set; }
        public Guid userOwnerId{ get; set; }
        public int timesUpdated{ get; set; }
        public DateTime expectedCompletionTime{ get; set; }
        public DateTime actualCompletionTime{ get; set; }
        public List<MasterTicketItem> masterTicketItems{ get; set; }
        }

具体孩子班级:

public class ApptTaskTicket : MasterTicket
    {
        public DateTime currentApptTime;
        public string patientName;
        //TODO: Create foreign relationship
        public Guid subjectPrsnlId;
        public string patientPhone;
        public string patientEmail;
        public string preferredContactMethod;
    }

控制器示例:

public class QueueController : Controller
    {
        private static readonly IList<MasterTicket> tickets;

        private static readonly IEnumerable<MasterTicket> combined;

        static QueueController()
        {
            tickets = new List<MasterTicket>
            {
                new ApptTaskTicket
                {
                    id = Guid.NewGuid(),
                    summary = "Foopy",
                    description = "Please set up Foop Dawg."
                },
                new ApptTaskTicket
                {
                    id = Guid.NewGuid(),
                    summary = "Milk man",
                    description = "Milkman here I come"
                },
                new ApptTaskTicket
                {
                    id = Guid.NewGuid(),
                    summary = "InMode Presentation",
                    description = "Upcoming presentation next month"
                },
            };

            CalendarQuickStart eventFetcher = new CalendarQuickStart();

            IList<MasterTicket> addAppts = eventFetcher.LoadAppointmentTasks();

            combined = tickets.Concat(addAppts);

            tickets.Concat(addAppts);
        }
        // GET: Queue
        public ActionResult Queue()
        {

            return View(combined);
        }
    }

查看页面以列表的形式呈现此列表:

@model IEnumerable<AffirmativeServiceSystem.Models.MasterTicket>

@{
    ViewBag.Title = "Queue";
}

<h2>Queue</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        @*<th>
            @Html.DisplayNameFor(model => model.openTime)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.closeTime)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.active)
        </th>*@
        <th>
            @Html.DisplayNameFor(model => model.summary)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.description)
        </th>
        @*<th>
            @Html.DisplayNameFor(model => model.updateTime)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.userUpdateId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.externalAppId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.userOpenId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.userOwnerId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.timesUpdated)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.expectedCompletionTime)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.actualCompletionTime)
        </th>*@
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        @*<td>
            @Html.DisplayFor(modelItem => item.openTime)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.closeTime)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.active)
        </td>*@
        <td>
            @Html.DisplayFor(modelItem => item.summary)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.description)
        </td>
        @*<td>
            @Html.DisplayFor(modelItem => item.updateTime)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.userUpdateId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.externalAppId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.userOpenId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.userOwnerId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.timesUpdated)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.expectedCompletionTime)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.actualCompletionTime)
        </td>*@
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.id }) |
            @Html.ActionLink("Details", "Details", new { id=item.id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.id })
        </td>
    </tr>
}

</table>

以后可以根据需要包括日历代码功能,但是现在我认为还可以。

我希望能够调用子具体类的抽象属性和具体属性,但实际上,当我尝试使用Intellisense编写代码生成的视图页面时,我只看到基本MasterTicket类的属性。 我说的时候应该使用多个模型,尝试使用不同的子级具体类,例如基础票证的不同票证类型吗? 想法是让一个具体的类用于日历中的约会确认,而另一类用于支持类事件。

提前欣赏您的想法。

我不确定我是否完全理解您的问题,但是我可以给您一些提示。 这并不是真正的回应,但是将其发布为评论太乱了。

提示:

  • 不要创建没有任何抽象属性或函数的抽象类。

    当您需要更多类的公共父对象(不应初始化父对象)时 ,请使用受保护的构造函数。

  • 当该父级只有一个孩子时,创建父级或抽象类没有任何意义。

  • 抽象类的真正含义是无需说明即可实现功能。

请参阅以下简单的“阅读器”示例:

public abstract class Reader
{
  public int ReadByte()
  {
    byte[] value = new byte[1];
    int read = Read(value, 0, 1);
    if (read == 0)
    {
      return -1;
    }

    return value[0];
  }

  public abstract int Read(byte[] value, int offset, int count);
}

public class DiskReader : Reader
{
  // TODO: implement reading from disk
  public override int Read(byte[] value, int offset, int count) => throw new System.NotImplementedException();
}

public class PortReader : Reader
{
  // TODO: implement reading from serial port
  public override int Read(byte[] value, int offset, int count) => throw new System.NotImplementedException();
}

public class NetworkReader : Reader
{
  // TODO: implement reading from network connection
  public override int Read(byte[] value, int offset, int count) => throw new System.NotImplementedException();
}

没有真正的实现,但是您应该明白这一点。 当您不使用抽象类中的某些抽象函数时,则无需创建抽象类。 请参见ReadByte函数中未实现函数的使用。

属性也是如此。 当您不使用未实现的功能时,最好使用接口。

对于您的问题:“为什么您可以看到子属性”

很简单。 当您有一个父类时,您将看不到子属性。 对于父类,只有父定义的方法和属性才可见。 您需要重新键入您的子类,以将其用作具有所有方法和属性的子类。

当您需要更多的孩子并且有一个功能时,使用父母是有意义的,该功能可用于具有相同属性/功能的所有孩子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM