显示不同对象的数组c#(类继承)

时间:2017-10-25 09:27:00

标签: c# class object inheritance

我的代码出了问题。我是继承人的新手(到目前为止只有1次讲座)并且非常感谢这里的任何帮助。我已经得到了这个问题,并认为我已经完成了它。创建一个Book类,添加两个子类。全部显示。加上其他东西,但这是核心问题。

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

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

5 个答案:

答案 0 :(得分:1)

您需要在if(bookArray [i] .GetType()== typeof(TextBook)) - 分支

中强制转换为特定类型的教科书

例如:

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(模式),但我不想干扰你的老师。

答案 1 :(得分:1)

另外,您可以重新定义类并避免在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);
        }

答案 2 :(得分: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());
        }

    }

答案 3 :(得分:1)

您可以用更短的格式重写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);
}

答案 4 :(得分:0)

想象一下,如果你添加更多来自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))
{
}

如果实际显示Book的代码发挥作用,情况会变得更糟。

你能做些什么来解决这个问题?首先介绍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类 - 他们就是这种情况,因为他们执行价格检查)和演示,你会这样做,如果您只需覆盖ToString即可获得所需的演示文稿。