簡體   English   中英

為什么要在繼承中使用受保護的變量(成員/屬性)? 使用它有什么好處?

[英]Why should I use protected variables(members/property) with Inheritance? What are the advantages of using it?

我正在瀏覽Begining C# 3.0 的代碼示例並遵循示例代碼。

當我創建了一個公共/受保護的方法時,我就可以使用派生類的對象訪問該方法。 前任:

class clsBuilding
    {
    protected string address { get; set; }
    protected Decimal purchasePrice { get; set; }
    protected decimal monthlyPayment { get; set; }
    protected Decimal taxes { get; set; }
    protected decimal insurance { get; set; }
    protected DateTime datePurchased { get; set; }
    protected int buildingType { get; set; }


     public void PropertySummary(string[] desc)
        {
            desc[0] = "Property Type:  "+whichType[buildingType] +
                        "," + address +
                        ",Cost: " + purchasePrice.ToString("C")+
                        ", Monthly Payment:" + monthlyPayment.ToString("C");
            desc[1] = "Insurance: " + insurance.ToString("C") +
                        " Taxes:  " + taxes.ToString("C")+
                            "Date Purchased: " + datePurchased.ToShortDateString();
            desc[2] = "";
        }
..............
}

class clsApartment : clsBuilding
    {
      ........................
}
.......
myApt = new clsApartment();

myApt.PropertySummary(desc);

但是我在父類開始時聲明的受保護財產的用途是什么。 當我嘗試通過使用派生類的對象或直接按照書中的說明訪問它們時:

只是為了將重點帶回家,在 clsBuilding(父類)中給出一行:

protected decimal purchase price;

你可以有這條線:

你可以有 line purchaseprice = 150000M ; 在課堂上,這是完全可以接受的。 (第15章,第447頁第4段之后),都​​沒有嘗試成功。

我敢肯定,我一定是概念錯誤或遺漏了什么。 如果不是,那么為什么有人會聲明受保護的變量或屬性?

編輯:

public class clsBuilding
{
    //--------------------- Symbolic constants -------------------
    public const int APARTMENT = 1;
    public const int COMMERCIAL = 2;
    public const int HOME = 3;

    private string[] whichType = { "", "Apartment", "Commercial", "Home" };

    //--------------------- Instance variables -------------------
    protected string address;
    protected decimal purchasePrice;
    protected decimal monthlyPayment;
    protected decimal taxes;
    protected decimal insurance;
    protected DateTime datePurchased;
    protected int buildingType;
    //--------------------- Constructor --------------------------
    public clsBuilding()
    {
        address = "Not closed yet";
    }

    public clsBuilding(string addr, decimal price, decimal payment,
                       decimal tax, decimal insur, DateTime date, int type):this()
    {
        if (addr.Equals("") == false)
            address = addr;
        purchasePrice = price;
        monthlyPayment = payment;
        taxes = tax;
        insurance = insur;
        datePurchased = date;
        buildingType = type;
    }
    //--------------------- Property Methods ---------------------

    public string Address
    {
        get
        {
            return address;
        }
        set
        {
            if (value.Length != 0)
                address = value;
        }
    }
    public decimal PurchasePrice
    {
        get
        {
            return purchasePrice;
        }
        set
        {
            if (value > 0M)
                purchasePrice = value;
        }
    }

    public decimal MonthlyPayment
    {
        get
        {
            return monthlyPayment;
        }
        set
        {
            if (value > 0M)
                monthlyPayment = value;
        }
    }

    public decimal Taxes
    {
        get
        {
            return taxes;
        }
        set
        {
            if (value > 0M)
                taxes = value;
        }
    }

    public decimal Insurance
    {
        get
        {
            return insurance;
        }
        set
        {
            if (value > 0M)
                insurance = value;
        }
    }

    public DateTime DatePurchased
    {
        get
        {
            return datePurchased;
        }
        set
        {
            if (value.Year > 2008)
                datePurchased = value;
        }
    }

    public int BuildingType
    {
        get
        {
            return buildingType;
        }
        set
        {
            if (value >= APARTMENT && value <= HOME)
                buildingType = value;
        }
    }
    //--------------------- General Methods ----------------------

    /*****
     * Purpose: Provide a basic description of the property
     * 
     * Parameter list:
     *  string[] desc       a string array to hold description
     *  
     * Return value:
     *  void
     *  
     * CAUTION: Method assumes that there are 3 elements in array
     ******/
    public void PropertySummary(string[] desc)
    {

        desc[0] = "Property type: " + whichType[buildingType] + 
                  ", " + address + 
                  ", Cost: " + purchasePrice.ToString("C") + 
                  ", Monthly payment: " + monthlyPayment.ToString("C");
        desc[1] = "     Insurance: " + insurance.ToString("C") + " Taxes: " + taxes.ToString("C") + 
                  "  Date purchased: " + datePurchased.ToShortDateString();
        desc[2] = " ";
    }

    /*****
     * Purpose: To call someone for snow removal, if available
     * 
     * Parameter list:
     *  n/a
     *  
     * Return value:
     *  string
     ******/
    public virtual string RemoveSnow()
    {
        return whichType[buildingType] + ": No snow removal service available.";
    }
}

class clsCommercial : clsBuilding
{
    //--------------------- Instance variables -------------------
    private int squareFeet;
    private int parkingSpaces;
    private decimal rentPerSquareFoot;

    //--------------------- Constructor --------------------------
    public clsCommercial(string addr, decimal price, decimal payment,
                        decimal tax, decimal insur, DateTime date, int type) :
                        base(addr, price, payment, tax, insur, date, type)
    {
        buildingType = type;   // Commercial type from base
    }
    //--------------------- Property Methods ---------------------
    public int SquareFeet
    {
        get
        {
            return squareFeet;
        }
        set
        {
            if (value > 0)
                squareFeet = value;
        }
    }
    public int ParkingSpaces
    {
        get
        {
            return parkingSpaces;
        }
        set
        {
            parkingSpaces = value;
        }
    }
    public decimal RentPerSquareFoot
    {
        get
        {
            return rentPerSquareFoot;
        }
        set
        {
            if (value > 0M)
                rentPerSquareFoot = value;
        }
    }

    //--------------------- General Methods ----------------------
    public override string RemoveSnow()
    {
        return "Commercial: Call Acme Snow Plowing: 803.234.5566";
    }

}


public frmMain()
    {
        InitializeComponent();
        myTime = DateTime.Now;

        myApt = new clsApartment("123 Ann Dotson Dr., Lexington, KY 40502", 550000, 6000,
                                             15000, 3400, myTime, 1);
        myComm = new clsCommercial("4442 Parker Place, York, SC 29745", 1200000, 9000,
                                        22000, 8000, myTime, 2);
        myHome = new clsHome("657 Dallas St, Ringgold, GA 30736", 260000, 1100,
                                    1750, 900, myTime, 3);
    }

可以從類訪問受保護的變量/屬性,如果我沒記錯的話,它是派生類。

通常,您會使用一個來防止該屬性被其他不從您的類繼承的類公開訪問。

受保護的成員可以像私有成員一樣被類的其他成員訪問。 派生類的成員也可以訪問受保護的成員。 這是私有和受保護之間的唯一區別。

在這種情況下, clsBuilding的作者打算讓受保護的屬性可用於任何派生類。 如果沒有派生類的具體演示,這不是一個特別好的例子。 也許您省略的clsApartment的詳細信息包含該演示——我當然希望是這樣。


這是您可以使用受保護的情況的人為示例。

abstract class Preference
{
    protected abstract void Load();
    protected abstract void Save();

    public Preference()
    {
        Load();
    }

    ~Preference()
    {
        Save();
    }
}

class IntPreference : Preference
{
    protected override void Load()
    {
        //load from registry or config file
    }

    protected override void Save()
    {
        //save to registry or config file
    }

    public int Value { get; set; }
}

class StringPreference : Preference
{
    ...
}

class FloatPreference : Preference
{
    ...
}

通過保護LoadSave方法,我們可以確保它們不是從Preference類或其后代之一外部調用的。 但是我們可以從基類調用LoadSave ,並且仍然擁有由知道如何處理持久性的派生類提供的實際實現。

我希望你已經涵蓋了虛擬方法!

建立在道格所說的基礎上。 Protected 使屬性、變量或函數可供子類使用,但不能從類外部使用。 如果您要使用私有,它仍然不能從類外部訪問,也不能從它的子類訪問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM