ptg 734 LISTING 17.11 Quote.cs using System; using System.Collections.Generic; public class Quote { private List<string> _quotes = new List<string>(); public string GetQuote() { Random rnd = new Random(); return _quotes[rnd.Next(_quotes.Count)]; } public Quote() { _quotes.Add(“All paid jobs absorb and degrade the mind Aristotle”); _quotes.Add(“No evil can happen to a good man, either in life or after death Plato”); _quotes.Add(“The only good is knowledge and the only evil is ignorance Plato”); } } The collection named _quotes is declared in the body of the class. That way, you can refer to the _quotes field in both the constructor and the GetQuote() method. NOTE You can create static constructor s by using the static keyword when declaring a con- structor. A static constructor is called once before any instance constructors. Overloading Methods and Constructors When a method is overloaded, a component contains two methods with exactly the same name. Many methods in .NET Framework are overloaded, including String.Replace(),Random.Next(), and Page.FindControl(). For example, here is a list of the three overloaded versions of the Random.Next() method: . Next()—Returns a random number between 0 and 2,147,483,647. . Next(upperbound)—Returns a number between 0 and the upper bound. . Next(lowerbound, upperbound)—Returns a number between the lower bound and the upper bound. CHAPTER 17 Building Components From the Library of Wow! eBook ptg 735 Building Basic Components 17 Because all three methods do the same thing—they all return a random number—it makes sense to overload the Next() method. The methods differ only in their signatures. A method signature consists of the order and type of parameters that a method accepts. For example, you can’t overload two methods that have exactly the same set of parameters (even if the names of the parameters differ). Overloading is useful when you want to associate related methods. Overloading is also useful when you want to provide default values for parameters. For example, the StoreProduct component in Listing 17.12 contains three overloaded versions of its SaveProduct() method. LISTING 17.12 StoreProduct.cs using System; public class StoreProduct { public void SaveProduct(string name) { SaveProduct(name, 0, String.Empty); } public void SaveProduct(string name, decimal price) { SaveProduct(name, price, String.Empty); } public void SaveProduct(string name, decimal price, string description) { // Save name, price, description to database } } You can call any of the three SaveProduct() methods in Listing 17.12 to save a new product. You can supply the new product with a name, a name and a price, or a name, a price, and a description. VISUAL WEB DEVELOPER NOTE When typing an overloaded method in Source view, the Intellisense pops up with all the different sets of parameters that you can use with the overloaded method (see Figure 17.4). From the Library of Wow! eBook ptg 736 Because a constructor is just a special method, you also can use overloading when declaring constructors for a class. For example, the ProductConstructor class in Listing 17.13 contains three overloaded constructors that can be used to initialize the Product class. LISTING 17.13 ProductConstructor.cs using System; public class ProductConstructor { public ProductConstructor(string name) : this(name, 0, String.Empty) { } public ProductConstructor(string name, decimal price) : this(name, price, String.Empty) { } public ProductConstructor(string name, decimal price, string description) { // Use name, price, and description } } When you instantiate the component in Listing 17.13, you can instantiate it in any of the following ways: ProductConstructor objProduct = new ProductConstructor(“Milk”); ProductConstructor objProduct = new ProductConstructor(“Milk”, 2.99d); ProductConstructor objProduct = new ProductConstructor(“Milk”, 2.99d, “While Milk”); Declaring Namespaces A namespace enables you to group logically related classes. You are not required to provide a class with a namespace. To this point, all the components you have seen created CHAPTER 17 Building Components FIGURE 17.4 Typing an overloaded method in V isual Web Developer. From the Library of Wow! eBook ptg 737 Building Basic Components 17 have been members of the global namespace. However, several advantages result from grouping components into namespaces. First, namespaces prevent naming collisions. If two companies produce a component with the same name, namespaces provide you with a method of distinguishing the components. Second, namespaces make it easier to understand the purpose of a class. If you group all your data access components into a DataAccess namespace and all your business logic components in a BusinessLogic namespace, you can immediately understand the function of a particular class. In an ASP.NET page, you import a namespace like this: <%@ Import Namespace=”System.Collections” %> In a C# component, on the other hand, you import a namespace like this: using System.Collections; You can create your own custom namespaces and group your components into name- spaces by using the namespace statement. For example, the component in Listing 17.14 is contained in the AspUnleashed.SampleCode namespace. LISTING 17.14 Namespaced.cs namespace AspNetUnleashed.SampleCode { public class Namespaced { public string SaySomething() { return “Something”; } } } The file in Listing 17.14 uses the Namespace statement to group the Namespaced compo- nent into the AspUnleashed.SampleCode namespace. Components in different files can share the same namespace, and different components in the same file can occupy differ- ent namespaces. The periods in a namespace name have no special significance. The periods are used to break up the words in the namespace, but you could use another character, such as an underscore character, instead. Microsoft recommends a certain naming convention when creating namespaces: CompanyName.TechnologyName[.Feature][.Design] From the Library of Wow! eBook ptg 738 So, if your company is named Acme Consulting and you are building a data access component, you might add your component to the following namespace: AcmeConsulting.DataAccess Of course this is simply a naming convention. No serious harm will come to you if you ignore it. Creating Partial Classes You can define a single component that spans multiple files by taking advantage of a feature of .NET Framework called partial classes. For example, the files in Listings 17.15 and 17.16 contain two halves of the same component. LISTING 17.15 FirstHalf.cs public partial class Tweedle { private string _message = @”THEY were standing under a tree, each with an arm round the other’s neck, and Alice knew which was which in a moment, because one of them had ““DUM”” embroidered on his collar, and the other ““DEE””.”; } LISTING 17.16 SecondHalf.cs public partial class Tweedle { public string GetMessage() { return _message; } } The private _message field is defined in the first file, but this private field is used in the GetMessage() method in the second file. When the GetMessage() method is called, it returns the value of the private field from the other class. Both files define a class with the same name. The class declaration includes the keyword Partial, which marks the classes as partial classes. CHAPTER 17 Building Components From the Library of Wow! eBook ptg 739 Building Basic Components 17 NOTE Partial classes are the basis for code-behind pages in the ASP.NET Framework. The code-behind file and the presentation page are two partial classes that get compiled into the same class. Inheritance and Abstract Classes When one class inherits from a second class, the inherited class automatically includes all the nonprivate methods and properties of its parent class. In other words, what’s true of the parent is true of the child, but not the other way around. Inheritance is used throughout .NET Framework. For example, every ASP.NET page inher- its from the base System.Web.UI.Page class. The only reason that you can use properties such as the IsPostback property in an ASP.NET page is that the page derives from the base Page class. All classes in .NET Framework derive from the base System.Object class. The Object class is the great-grandmother of every other class. This means that any methods or properties of the Object class, such as the ToString() method, are shared by all classes in the Framework. You can take advantage of inheritance when building your own components. You indicate that one class inherits from a second class when you declare a class. For example, the file in Listing 17.17 includes three components: a BaseProduct class, a ComputerProduct class, and a TelevisionProduct class. LISTING 17.17 Inheritance.cs public class BaseProduct { private decimal _price; public decimal Price { get { return _price; } set { _price = value; } } } public class ComputerProduct : BaseProduct { private string _processor; public string Processor { get { return _processor; } set { _processor = value; } From the Library of Wow! eBook ptg 740 } } public class TelevisionProduct : BaseProduct { private bool _isHDTV; public bool IsHDTV { get { return _isHDTV; } set { _isHDTV = value; } } } Both the ComputerProduct and TelevisionProduct components inherit from the BaseProduct component. Because the BaseProduct class includes a Price property, both inherited components automatically inherit this property. When inheriting one class from another, you also can override methods and properties of the base class. Overriding a method or property is useful when you want to modify the behavior of an existing class. To override a property or method of a base class, the property or method must be marked with the C# virtual or abstract keyword or the Visual Basic .NET Overridable or MustOverride keyword. Only methods or properties marked with the virtual or abstract keyword can be overridden. For example, the file in Listing 17.18 contains two components: a ProductBase class and a OnSaleProduct class. The second class inherits from the first class and overrides its Price property. The Price property of the OnSaleProduct component divides the price by half. LISTING 17.18 OnSaleProduct.cs public class ProductBase { private decimal _price; public virtual decimal Price { get { return _price; } set { _price = value; } } } public class OnSaleProduct : ProductBase CHAPTER 17 Building Components From the Library of Wow! eBook ptg 741 Building Basic Components 17 { override public decimal Price { get { return base.Price / 2; } set { base.Price = value; } } } The base keyword (MyBase in Visual Basic) is used in Listing 17.18 to refer to the base class (the ProductBase class). Finally, you can use the abstract keyword when declaring a class to mark it as a class that requires inheritance. You cannot instantiate an abstract class. To use an abstract class, you must derive a new class from the abstract class and instantiate the derived class. Abstract classes are the foundation for the ASP.NET Provider Model. Personalization, Membership, Roles, Session State, and Site Maps all use the Provider Model. For example, the MembershipProvider class is the base class for all Membership Providers. The SqlMembershipProvider and ActiveDirectoryMembershipProvider classes both derive from the base MembershipProvider class. NOTE Chapter 27, “Using ASP.NET Membership,” discusses the MembershipProvider class- es in detail, which is responsible for saving and loading membership information such as application usernames and passwords. The base MembershipProvider class is an abstract class. You cannot use this class directly in your code. Instead, you must use one of its derived classes. However, the base MembershipProvider class provides a common set of methods and properties that all MembershipProvider-derived classes inherit. The base MembershipProvider class includes a number of methods and properties marked as abstract. A derived MembershipProvider class is required to override these properties and methods. The file in Listing 17.19 contains two components. The first component, the BaseEmployee component, is an abstract class that contains an abstract property named Salary. The second component, the SalesEmployee, inherits the BaseEmployee compo- nent and overrides the Salary property. LISTING 17.19 Employees.cs public abstract class BaseEmployee { public abstract decimal Salary { get; From the Library of Wow! eBook ptg 742 } public string Company { get { return “Acme Software”; } } } public class SalesEmployee : BaseEmployee { public override decimal Salary { get { return 67000.23m; } } } Declaring Interfaces An interface is a list of properties and methods that a class must implement. If a class implements an interface, you know that the class includes all the properties and methods contained in the interface. For example, the file in Listing 17.20 contains an interface named IProduct and two components named MusicProduct and BookProduct. LISTING 17.20 Products.cs public interface IProduct { decimal Price { get; } void SaveProduct(); } public class MusicProduct : IProduct { public decimal Price { get { return 12.99m; } } CHAPTER 17 Building Components From the Library of Wow! eBook ptg 743 Building Basic Components 17 public void SaveProduct() { // Save Music Product } } public class BookProduct : IProduct { public decimal Price { get { return 23.99m; } } public void SaveProduct() { // Save Book Product } } Both components in Listing 17.17 are declared as implementing the IProduct interface. (The colon can mean implements or inherits.) Furthermore, both components include the SaveProduct() method and the Price property. Both components are required to have this method and property because they are declared as implementing the IProduct interface. Interfaces are similar to abstract classes with two important differences. First, a compo- nent can inherit from only one class. On the other hand, a component can implement many different interfaces. Second, an abstract class can contain application logic. You can add methods to an abstract class that all derived classes inherit and can use. An interface, on the other hand, cannot contain any logic. An interface is nothing more than a list of methods and properties. Using Access Modifiers C# supports the following access modifiers, which you can use when declaring a class, method, or property: . Public—A public class, method, or property has no access restrictions. . Protected—A protected method or property can be accessed only within the class itself or a derived class. From the Library of Wow! eBook . example, every ASP. NET page inher- its from the base System.Web.UI.Page class. The only reason that you can use properties such as the IsPostback property in an ASP. NET page is that the page. example, the component in Listing 17. 14 is contained in the AspUnleashed.SampleCode namespace. LISTING 17. 14 Namespaced.cs namespace AspNetUnleashed.SampleCode { public class Namespaced { public string. 17. 14 uses the Namespace statement to group the Namespaced compo- nent into the AspUnleashed.SampleCode namespace. Components in different files can share the same namespace, and different components