Sealed Classes Application pot

6 117 0
Sealed Classes Application pot

Đang tải... (xem toàn văn)

Thông tin tài liệu

Sealed Classes Using inheritance is not always easy and requires forethought. If you create an interface or an abstract class, you are knowingly writing something that will be inherited from in the future. The trouble is that predicting the future is a difficult business. It takes skill, effort, and knowledge of the problem you are trying to solve to craft a flexible, easy-to-use hierarchy of interfaces, abstract classes, and classes. To put it another way, unless you consciously design a class with the intention of using it as a base class, it's extremely unlikely that it will function very well as a base class. Fortunately, C# allows you to use the sealed keyword to prevent a class from being used as a base class if you decide that it should not be. For example: sealed class LiteralToken : DefaultTokenImpl, IToken { } If any class attempts to use LiteralToken as a base class, a compile-time error will be generated. A sealed class cannot declare any virtual methods. The sole purpose of the virtual keyword is to declare that this is the first implementation of a method that you intend to override in a derived class, but a sealed class cannot be derived from. NOTE A struct is implicitly sealed. You can never derive from a struct. Sealed Methods You can also use the sealed keyword to declare that an individual method is sealed. This means that a derived class cannot then override the sealed method. You can only seal an override method (you declare the method as sealed override).You can think of the interface, virtual, override, and sealed keywords as follows: • An interface introduces the name of a method. • A virtual method is the first implementation of a method. • An override method is another implementation of a method. • A sealed method is the last implementation of a method. Subscribing to an Event Like delegates, events come ready-made with a += operator. You subscribe to an event by using this += operator. In the automated factory, the software controlling each machine can arrange for the shutdown methods to be called when the MachineOverheating event is raised like this: TemperatureMonitor tempMonitor = new TemperatureMonitor(); tempMonitor.MachineOverheating += delegate { folder.StopFolding(0) }; tempMonitor.MachineOverheating += welder.FinishWelding; tempMonitor.MachineOverheating += painter.PaintOff; N otice that the syntax is the same as for adding a method to a delegate. You can even subscribe by using an anonymous method. When the tempMonitor.MachineOverheating event runs, it will call all the subscribing methods and shut the machines down. Summarizing Keyword Combinations The following table summarizes the various valid (yes) and invalid (no) keyword combinations. Keyword Interface Abstract class Class Sealed class struct Abstract no yes no no no New yes* yes yes yes no† override no yes yes yes no‡ private no yes yes yes yes protected no yes yes yes no** public no yes yes yes yes sealed no yes yes yes no virtual no yes yes no no * An interface can extend another interface and introduce a new method with the same signautre. † A struct implicitly derives from System.Object, which contains methods that the struct can hide. ‡ A struct implicitly derives from System.Object, which contains no virtual methods. ** A struct is implicitly sealed and cannot be derived from. • If you want to continue to the next chapter Keep Visual Studio 2005 running and turn to Chapter 13. • If you want to exit Visual Studio 2005 now On the File menu, click Exit. If you see a Save dialog box, click Yes. The Problem with Objects In order to understand Generics, it is worth looking in detail at the problems they are designed to solve, specifically when using the object type. You can use the object type as a reference to any type of value or variable. All reference types automatically inherit (either directly or indirectly) from the System.Object class in the .NET Framework. You can use this information to create highly generalized classes and methods. For example, many of the classes in the System.Collections namespace exploit this fact to allow you to create collections of any type. You will also notice in the System.Collections.Queue class that you can create queues containing almost anything (you have already been introduced to the collection classes in Chapter 10, “Using Arrays and Collections”). The following fragment shows how to create and manipulate a queue of Circle objects: using System.Collections; Queue myQueue = new Queue(); Circle myCircle = new Circle(); myQueue.Enqueue(myCircle); myCircle = (Circle)myQueue.Dequeue(); The Enqueue method adds an object to the head of a queue, and the Dequeue method removes the object at the other end of the queue. These methods are defined like this: public void Enqueue( object item ); public object Dequeue(); Because the Enqueue and Dequeue methods manipulate objects, you can operate on queues of Circles, PhoneBooks, Clocks, or any of the other classes you have seen in earlier exercises in this book. However, it is important to notice that you have to cast the value returned by the Dequeue method to the appropriate type because the compiler will not perform the conversion from the object type automatically. If you don't cast the returned value, you will get the compiler error “Cannot implicitly convert type 'object' to 'Circle'” as shown in the following code fragment: Circle myCircle = new Circle(); myQueue.Enqueue(myCircle); myCircle = (Circle)myQueue.Dequeue(); // Cast is mandatory This need to perform an explicit cast denigrates much of the flexibility afforded by the object type. It is very easy to write code such as this: Queue myQueue = new Queue(); Circle myCircle = new Circle(); myQueue.Enqueue(myCircle); Clock myClock = (Clock)myQueue.Dequeue(); Although this code will compile, it is not valid and throws a System.InvalidCastException at runtime. The error is caused by trying to store a reference to a Circle in a Clock variable, and the two types are not compatible. This error is not spotted until runtime because the compiler does not have enough information. It can only determine the real type of the object being dequeued at runtime. Another disadvantage of using the object approach to create generalized classes and methods is that it can use additional memory and processor time if the runtime needs to convert an object into a value type and back again. Consider the following piece of code that manipulates a queue of ints: Queue myQueue = new Queue(); int myInt = 99; myQueue.Enqueue(myInt); // box the int to an object myInt = (int)myQueue.Dequeue(); // unbox the object to an int The Queue data type expects the items it holds to be reference types. Enqueueing a value type, such as an int, requires that it is boxed to convert it into a reference type. Similarly, dequeueing into an int requires that the item is unboxed to convert it back to a value type. See the sections “Boxing” and “Unboxing” in Chapter 8 for more details. Although boxing and unboxing happen transparently, they add a performance overhead as they involve dynamic memory allocations. While this overhead is small for each item, it adds up when a program creates queues of large numbers of value types. Run the Application 1. On the Debug menu, click Start Without Debugging to run the application. 2. Type in a first name and a last name, and then select a tower from the list. Click Add. In the message box that appears displaying the member data you entered, click OK. 3. Try and close the form. In the message box that appears, click No. The form should continue running. 4. Try and close the form again. In the message box, click Yes. This time the form closes and the application finishes. • If you want to continue to the next chapter Keep Visual Studio 2005 running and turn to Chapter 21. • If you want to exit Visual Studio 2005 for now On the File menu, click Exit. If you see a Save dialog box, click Yes.  . derived class, but a sealed class cannot be derived from. NOTE A struct is implicitly sealed. You can never derive from a struct. Sealed Methods You can also use the sealed keyword to declare. an individual method is sealed. This means that a derived class cannot then override the sealed method. You can only seal an override method (you declare the method as sealed override).You can. Fortunately, C# allows you to use the sealed keyword to prevent a class from being used as a base class if you decide that it should not be. For example: sealed class LiteralToken : DefaultTokenImpl,

Ngày đăng: 01/07/2014, 09:20

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan