【问题标题】:display array of different objects c# (class inheritance)显示不同对象的数组c#(类继承)
【发布时间】:2017-10-25 09:26:59
【问题描述】:

我的代码有问题。我是继承的新手(到目前为止只有 1 节课),希望能在这里得到任何帮助。我已经遇到了这个问题,并且认为我已经完成了。创建一个 Book 类,添加两个子类。全部显示。加上其他东西,但这是核心问题。

当我尝试在 for 循环中显示每个对象及其信息时,我无法弄清楚如何访问教科书的 BookGrade。我制作了一系列书籍并将所有内容都放在那里。我知道这是不对的,但我不知道从哪里开始。我试过制作这样的教科书数组

TextBook[] bookArray = new TextBook[3] { Book1, TBook1, CBook1};

然后我需要向 Book1 添加一个演员表,这有效,但我仍然无法将类型“CoffeeTableBook”隐式转换为“TextBook”。我明白了,但不知道如何解决它。我收到此错误“'Book' 不包含 'BookGrade' 的定义..”

我有 3 个课程,Book、TextBook 和 CoffeeTableBook。 TextBook 和 CoffeeTableBook 类都派生自 Book 类。

提前感谢任何花时间帮助我的人。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BookDemo
{
class Program
{
    static void Main(string[] args)
    {
        //Book
        Book Book1 = new Book();
        Book1.BookNum = 123456;
        Book1.BookTitle = "Harry Potter 1";
        Book1.BookAuthor = "JK Rowling";
        Book1.BookPrice = 5.95;

        //Text Book
        TextBook TBook1 = new TextBook();
        TBook1.BookNum = 123436;
        TBook1.BookTitle = "Harry Potter 2";
        TBook1.BookAuthor = "JK Rowling";
        TBook1.BookPrice = 5.95;
        TBook1.BookGrade = "A";


        //Coffee Table Book
        CoffeeTableBook CBook1 = new CoffeeTableBook();
        CBook1.BookNum = 123136;
        CBook1.BookTitle = "Harry Potter 7";
        CBook1.BookAuthor = "JK Rowling";
        CBook1.BookPrice = 95.95;

        Book[] bookArray = new Book[3] { Book1, TBook1, CBook1 };


        for (int i = 0; i < bookArray.Length; i++)
        {
            if (bookArray[i].GetType() == typeof(TextBook))
            {
                Console.WriteLine("{0} {1} {2} {3} {4}", bookArray[i].BookNum, bookArray[i].BookTitle, bookArray[i].BookAuthor, bookArray[i].BookPrice, bookArray[i].BookGrade);//'Book' does not contain a defination for 'BookGrade'..
            }
            else
            {
                Console.WriteLine("{0} {1} {2} {3} {4}", bookArray[i].BookNum, bookArray[i].BookTitle, bookArray[i].BookAuthor, bookArray[i].BookPrice, "N/A");
            }
        }
    }

}

}

class Book
{
public int BookNum { get; set; }
public string BookTitle { get; set; }
public string BookAuthor { get; set; }
public double BookPrice { get; set; }

}

class TextBook : Book // must be priced between $20.00 and $80.00
{
const double MIN_PRICE = 20;
const double MAX_PRICE = 80;
public string BookGrade { get; set; }

new public double BookPrice
{
    set
    {
        if (value < MIN_PRICE)
        {
            base.BookPrice = MIN_PRICE;
        }
        else if (value > MAX_PRICE)
        {
            base.BookPrice = MAX_PRICE;
        }
        else
        {
            base.BookPrice = value;
        }
    }
    get
    {
        return base.BookPrice;
    }
}
}

class CoffeeTableBook : Book //must be priced between $35.00 and $100.00
{
const double MIN_PRICE = 35;
const double MAX_PRICE = 100;
new public double BookPrice
{
    set
    {
        if (value < MIN_PRICE)
        {
            base.BookPrice = MIN_PRICE;
        }
        else if (value > MAX_PRICE)
        {
            base.BookPrice = MAX_PRICE;
        }
        else
        {
            base.BookPrice = value;
        }
    }
    get
    {
        return base.BookPrice;
    }
}
}

【问题讨论】:

    标签: c# class object inheritance


    【解决方案1】:

    您可以重写 'toString()' 方法来设置显示对象的确切方式

    class Program
    {
        class Book
        {
            public int BookNum { get; set; }
            public string BookTitle { get; set; }
            public string BookAuthor { get; set; }
            public double BookPrice { get; set; }
    
            public override string ToString() //!
            {
                return string.Format("{0} {1} {2} {3}", this.BookNum, this.BookTitle, this.BookAuthor, this.BookPrice);
            }
        }
    
        class TextBook : Book // must be priced between $20.00 and $80.00
        {
            const double MIN_PRICE = 20;
            const double MAX_PRICE = 80;
            public string BookGrade { get; set; }
    
            new public double BookPrice
            {
                set
                {
                    if (value < MIN_PRICE)
                    {
                        base.BookPrice = MIN_PRICE;
                    }
                    else if (value > MAX_PRICE)
                    {
                        base.BookPrice = MAX_PRICE;
                    }
                    else
                    {
                        base.BookPrice = value;
                    }
                }
                get { return base.BookPrice; }
            }
    
            public override string ToString() //!
            {
                return base.ToString() + " " + this.BookGrade;
            }
        }
    
        class CoffeeTableBook : Book //must be priced between $35.00 and $100.00
        {
            const double MIN_PRICE = 35;
            const double MAX_PRICE = 100;
    
            new public double BookPrice
            {
                set
                {
                    if (value < MIN_PRICE)
                    {
                        base.BookPrice = MIN_PRICE;
                    }
                    else if (value > MAX_PRICE)
                    {
                        base.BookPrice = MAX_PRICE;
                    }
                    else
                    {
                        base.BookPrice = value;
                    }
                }
                get { return base.BookPrice; }
            }
        }
    
        private static void Main(string[] args)
        {
            //Book
            var book1 = new Book
            {
                BookNum = 123456,
                BookTitle = "Harry Potter 1",
                BookAuthor = "JK Rowling",
                BookPrice = 5.95
            };
    
            //Text Book
            var TBook1 = new TextBook
            {
                BookNum = 123436,
                BookTitle = "Harry Potter 2",
                BookAuthor = "JK Rowling",
                BookPrice = 5.95,
                BookGrade = "A"
            };
    
    
            //Coffee Table Book
            var CBook1 = new CoffeeTableBook
            {
                BookNum = 123136,
                BookTitle = "Harry Potter 7",
                BookAuthor = "JK Rowling",
                BookPrice = 95.95
            };
    
            var bookArray = new Book[] {book1, TBook1, CBook1};
    
    
            foreach (Book t in bookArray)
            {
                Console.WriteLine(t); //! i.e Console.WriteLine(t.ToString());
            }
    
        }
    

    【讨论】:

      【解决方案2】:

      您需要在 if (bookArray[i].GetType() == typeof(TextBook))-Branch 中转换为特定类型的教科书

      例如:

      if (bookArray[i].GetType() == typeof(TextBook))
      {
          Console.WriteLine("{0} {1} {2} {3} {4}", bookArray[i].BookNum, bookArray[i].BookTitle, bookArray[i].BookAuthor, bookArray[i].BookPrice, ((TextBook)bookArray[i]).BookGrade); // Works now, because we view bookArray[i] as TextBook and not it's underlaying type
      }
      else
      {
          Console.WriteLine("{0} {1} {2} {3} {4}", bookArray[i].BookNum, bookArray[i].BookTitle, bookArray[i].BookAuthor, bookArray[i].BookPrice, "N/A");
      }
      

      我通常建议使用here 描述的新 Switch-Capabilities(模式),但我不想干扰你的老师。

      【讨论】:

      • 我试过 (TextBook)bookArray[i].BookGrade 而不是 ((TextBook)bookArray[i]).BookGrade) 干杯
      • 这会改变 BookGrade 的类型而不是 bookArray[i] :)
      【解决方案3】:

      或者,您可以重新定义您的类并避免检查 for 中的类型:

      class Book
      {
      public int BookNum { get; set; }
      public string BookTitle { get; set; }
      public string BookAuthor { get; set; }
      public double BookPrice { get; set; }
      public string BookGrade = "N/A";
      
      }
      
      class TextBook : Book // must be priced between $20.00 and $80.00
      {
      const double MIN_PRICE = 20;
      const double MAX_PRICE = 80;
      public string BookGrade { get; set; }
      
      new public double BookPrice
      {
          set
          {
              if (value < MIN_PRICE)
              {
                  base.BookPrice = MIN_PRICE;
              }
              else if (value > MAX_PRICE)
              {
                  base.BookPrice = MAX_PRICE;
              }
              else
              {
                  base.BookPrice = value;
              }
          }
          get
          {
              return base.BookPrice;
          }
      }
      }
      
      class CoffeeTableBook : Book //must be priced between $35.00 and $100.00
      {
      const double MIN_PRICE = 35;
      const double MAX_PRICE = 100;
      new public double BookPrice
      {
          set
          {
              if (value < MIN_PRICE)
              {
                  base.BookPrice = MIN_PRICE;
              }
              else if (value > MAX_PRICE)
              {
                  base.BookPrice = MAX_PRICE;
              }
              else
              {
                  base.BookPrice = value;
              }
          }
          get
          {
              return base.BookPrice;
          }
      }
      }
      

      主要是:

      foreach (Book singleBook in BookArray)
              {
      
              Console.WriteLine("{0} {1} {2} {3} {4}", singleBook.BookNum, singleBook.BookTitle, singleBook.BookAuthor, singleBook.BookPrice, singleBook.BookGrade);
              }
      

      【讨论】:

        【解决方案4】:

        你可以用更短的格式重写你的 for 循环:

        string output;
        
        foreach (Book bk in bookArray)
        {
            output = string.Format(
                         "{0} {1} {2} {3} {4}",
                         bk.BookNum,
                         bk.BookTitle,
                         bk.BookAuthor,
                         bk.BookPrice,
                         (bk is TextBook)
                             ? (bk as TextBook).BookGrade
                             : "N/A");
        
            Console.WriteLine(output);
        }
        

        【讨论】:

          【解决方案5】:

          想象一下,如果您添加更多从 Book 派生的类会发生什么,您的代码最终会变得笨拙

          if(book.GetType() == typeof(TextBook))
          {
          }
          if(book.GetType() == typeof(CoffeeTableBook))
          {
          }
          if(book.GetType() == typeof(AnotherBookType))
          {
          }
          if(book.GetType() == typeof(MagicalSpellsBook))
          {
          }
          if(book.GetType() == typeof(Whatever))
          {
          }
          

          如果实际显示Books 的代码开始起作用,情况会变得更糟。

          你能做些什么来解决这个问题?首先介绍一个BookRenderer

          class BookRenderer
          {
              List<ISpecificBookRenderer> specificBookRenderers = ...; // pass via constructor
          
              public void RenderBook(Book b)
              {
                  var matchingRenderer = specificBookRenderers.First(r => r.BookType == b.GetType());
                  matchingRenderer.RenderBook(b);
              }
          }
          

          派生自ISpecificBookRenderer 的类型负责呈现您的图书。接口ISpecificBookRenderer定义为

          interface ISpecificBookRenderer 
          {
              Type BookType { get; }
          
              void RenderBook(Book b);
          }
          

          现在您可以为从Book 派生的每种类型创建一个渲染器,例如

          class TextBookRenderer
          {
              public Type BookType => typeof(TextBook);
          
              public void RenderBook(Book b)
              {
                  if(b is TextBoox textBook)
                  {
                      // output TextBook value
                  }
          
                  throw new ArgumentException("Passed book is not a TextBook", nameof(b));
              }
          }
          

          当然,这是有代价的,但单节课保持整洁。此外,可以想象需要将您的书籍渲染到不同的系统。引入这些渲染器允许您在不更改实际类的情况下交换实现。 并且您不会将业务逻辑(您的 Book 类 - 在这种情况下是它们,因为它们执行价格检查)与演示文稿混淆,如果您只是覆盖 @ 987654332@实现您想要的演示。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-01-04
            • 2014-01-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-12-23
            相关资源
            最近更新 更多