Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C# 2008 Step by Step.pdf
Скачиваний:
17
Добавлен:
25.03.2016
Размер:
13.96 Mб
Скачать

Chapter 7 Creating and Managing Classes and Objects

127

Naming and Accessibility

The following recommendations relate to the naming conventions for fields and methods based on the accessibility of class members:

Identifiers that are public should start with a capital letter. For example,

Area starts with “A” (not “a”) because it’s public. This system is known as the

PascalCase naming scheme (it was first used in the Pascal language).

Identifiers that are not public (which include local variables) should start with a lowercase letter. For example, radius starts with “r” (not “R”) because it’s private. This system is known as the camelCase naming scheme.

There’s only one exception to this rule: class names should start with a capital letter, and constructors must match the name of their class exactly; therefore, a private

constructor must start with a capital letter.

Important Don’t declare two public class members whose names differ only in case. If you do, your class will not be usable from other languages that are not case sensitive, such as Microsoft Visual Basic.

Working with Constructors

When you use the new keyword to create an object, the runtime has to construct that object by using the definition of the class. The runtime has to grab a piece of memory from the operating system, fill it with the fields defined by the class, and then invoke a constructor to perform any initialization required.

A constructor is a special method that runs automatically when you create an instance of a class. It has the same name as the class, and it can take parameters, but it cannot return a value (not even void). Every class must have a constructor. If you don’t write one, the compiler automatically generates a default constructor for you. (However, the compiler-generated default constructor doesn’t actually do anything.) You can write your own default constructor quite easily—just add a public method with the same name as the class that does not return

a value. The following example shows the Circle class with a default constructor that initializes the radius field to 0:

class Circle

{

public Circle() // default constructor

{

radius = 0;

}

128

Part II Understanding the C# Language

public double Area()

{

return Math.PI * radius * radius;

}

private int radius;

}

Note In C# parlance, the default constructor is a constructor that does not take any parameters. It does not matter whether the compiler generates it or you write it; it is still the default constructor. You can also write nondefault constructors (constructors that do take parameters), as you will see in the upcoming section titled “Overloading Constructors.”.

Note that the constructor is marked as public. If this keyword is omitted, the constructor

will be private (just like any other methods and fields). If the constructor is private, it cannot be used outside the class, which prevents you from being able to create Circle objects from methods that are not part of the Circle class. You might therefore think that private construc-

tors are not that valuable. However, they do have their uses, but they are beyond the scope of the current discussion.

You can now use the Circle class and exercise its Area method. Notice how you use dot notation to invoke the Area method on a Circle object:

Circle c;

c = new Circle();

double areaOfCircle = c.Area();

Overloading Constructors

You’re almost finished, but not quite. You can now declare a Circle variable, point it to a newly created Circle object, and then call its Area method. However, there is still one last problem. The area of all Circle objects will always be 0 because the default constructor sets the radius to 0 and it stays at 0; the radius field is private, and there is no way of changing its

value after it has been initialized. One way to solve this problem is to realize that a construc-

tor is just a special kind of method and that it—like all methods—can be overloaded. Just as there are several versions of the Console.WriteLine method, each of which takes different pa-

rameters, so too you can write different versions of a constructor. You can add a constructor to the Circle class, with the radius as its parameter, like this:

class Circle

{

public Circle() // default constructor

{

radius = 0;

}

Chapter 7 Creating and Managing Classes and Objects

129

public Circle(int initialRadius) // overloaded constructor

{

radius = initialRadius;

}

public double Area()

{

return Math.PI * radius * radius;

}

private int radius;

}

Note The order of the constructors in a class is immaterial; you can define constructors in whatever order you feel most comfortable with.

You can then use this constructor when creating a new Circle object, like this:

Circle c;

c = new Circle(45);

When you build the application, the compiler works out which constructor it should call based on the parameters that you specify to the new operator. In this example, you passed an int, so the compiler generates code that invokes the constructor that takes an int parameter.

You should be aware of a quirk of the C# language: if you write your own constructor for a class, the compiler does not generate a default constructor. Therefore, if you’ve written your own constructor that accepts one or more parameters and you also want a default constructor, you’ll have to write the default constructor yourself.

Partial Classes

A class can contain a number of methods, fields, and constructors, as well as other items discussed in later chapters. A highly functional class can become quite large. With C#, you can split the source code for a class into separate files so that you can organize the definition of a large class into smaller, easier to manage pieces. This feature is used by Microsoft Visual Studio 2008 for Windows Presentation Foundation (WPF) applications, where the source code that the developer can edit is maintained in a separate file from the code that is generated by Visual Studio whenever the layout of a form changes.

130

Part II Understanding the C# Language

When you split a class across multiple files, you define the parts of the class by using the partial keyword in each file. For example, if the Circle class is split between two files

called circ1.cs (containing the constructors) and circ2.cs (containing the methods and fields), the contents of circ1.cs look like this:

partial class Circle

{

public Circle() // default constructor

{

radius = 0;

}

public Circle(int initialRadius) // overloaded constructor

{

radius = initialRadius;

}

}

The contents of circ2.cs look like this:

partial class Circle

{

public double Area()

{

return Math.PI * radius * radius;

}

private int radius;

}

When you compile a class that has been split into separate files, you must provide all the files to the compiler.

In the following exercise, you will declare a class that models a point in two-dimensional space. The class will contain two private fields for holding the x- and y-coordinates of a point and will provide constructors for initializing these fields. You will create instances of the class by using the new keyword and calling the constructors.

Write constructors and create objects

1.Start Visual Studio 2008 if it is not already running.

2.Open the Classes project located in the \Microsoft Press\Visual CSharp Step by Step\ Chapter 7\Classes folder in your Documents folder.

3.In Solution Explorer, double-click the file Program.cs to display it in the Code and Text Editor window.

Chapter 7 Creating and Managing Classes and Objects

131

4.Locate the Main method in the Program class.

The Main method calls the Entrance method, wrapped in a try block and followed by a catch handler. With this try/catch block, you can write the code that would typically go inside Main in the Entrance method instead, safe in the knowledge that it will catch and handle any exceptions.

5.Display the file Point.cs in the Code and Text Editor window.

This file defines a class called Point, which you will use to represent the location of a point defined by a pair of x- and y-coordinates. The Point class is currently empty.

6.Return to the Program.cs file, and locate the Entrance method of the Program class. Edit the body of the Entrance method, replacing the // to do comment with the following statement:

Point origin = new Point();

7.On the Build menu, click Build Solution.

The code builds without error because the compiler automatically generates the code for a default constructor for the Point class. However, you cannot see the C# code for this constructor because the compiler does not generate any source language statements.

8.Return to the Point class in the file Point.cs. Replace the // to do comment with a public constructor that accepts two int arguments called x and y and that calls the Console. WriteLine method to display the values of these arguments to the console, as shown in bold type in the following code example. The Point class should look like this:

class Point

{

public Point(int x, int y)

{

Console.WriteLine(“x:{0}, y:{1}”, x, y);

}

}

Note Remember that the Console.WriteLine method uses {0} and {1} as placeholders. In the statement shown, {0} will be replaced with the value of x, and {1} will be replaced with the value of y when the program runs.

9.On the Build menu, click Build Solution. The compiler now reports an error:

‘Classes.Point’ does not contain a constructor that takes ‘0 ‘ arguments

132 Part II Understanding the C# Language

The call to the default constructor in Entrance no longer works because there is no longer a default constructor. You have written your own constructor for the Point class, so the compiler no longer generates the default constructor. You will now fix this by writing your own default constructor.

10.Edit the Point class, and add a public default constructor that calls Console.WriteLine to write the string “default constructor called” to the console, as shown in bold type in the following code example. The Point class should now look like this:

class Point

{

public Point()

{

Console.WriteLine(“default constructor called”);

}

public Point(int x, int y)

{

Console.WriteLine(“x:{0}, y:{1}”, x, y);

}

}

11.On the Build menu, click Build Solution. The program should now build successfully.

12.In the Program.cs file, edit the body of the Entrance method. Declare a variable called bottomRight of type Point, and initialize it to a new Point object by using the constructor with two arguments, as shown in bold type in the following code. Supply the values

1024 and 1280, representing the coordinates at the lower-right corner of the screen based on the resolution 1024 × 1280. The Entrance method should now look like this:

static void Entrance()

{

Point origin = new Point();

Point bottomRight = new Point(1024, 1280);

}

13.On the Debug menu, click Start Without Debugging.

The program builds and runs, displaying the following messages to the console:

default constructor called x:1024, y:1280

14.Press the Enter key to end the program and return to Visual Studio 2008.

You will now add two int fields to the Point class to represent the x- and y-coordinates of a point, and you will modify the constructors to initialize these fields.

Chapter 7 Creating and Managing Classes and Objects

133

15.Edit the Point class in the Point.cs file, and add two private instance fields called x and y of type int, as shown in bold type in the following code. The Point class should now look like this:

class Point

{

public Point()

{

Console.WriteLine(“default constructor called”);

}

public Point(int x, int y)

{

Console.WriteLine(“x:{0}, y:{1}”, x, y);

}

private int x, y;

}

You will now edit the second Point constructor to initialize the x and y fields to the values of the x and y parameters. There is a potential trap when you do this. If you are not careful, the constructor will look like this:

public Point(int x, int y) // Don’t type this!

{

x = x; y = y;

}

Although this code will compile, these statements appear to be ambiguous. How does the compiler know in the statement x = x; that the first x is the field and the second x is the parameter? It doesn’t! A method parameter with the same name as a field hides the field for all statements in the method. All this constructor actually does is assign the parameters to themselves; it does not modify the fields at all. This is clearly not what you want.

The solution is to use the this keyword to qualify which variables are parameters and which are fields. Prefixing a variable with this means “the field in this object.”

16.Modify the Point constructor that takes two parameters, and replace the Console. WriteLine statement with the following code shown in bold type:

public Point(int x, int y)

{

this.x = x; this.y = y;

}

134Part II Understanding the C# Language

17.Edit the default Point constructor to initialize the x and y fields to –1, as follows in bold

type. Note that although there are no parameters to cause confusion, it is still good practice to qualify the field references with this:

public Point()

{

this.x = -1; this.y = -1;

}

18.On the Build menu, click Build Solution. Confirm that the code compiles without errors or warnings. (You can run it, but it does not produce any output yet.)

Methods that belong to a class and that operate on the data belonging to a particular instance of a class are called instance methods. (There are other types of methods that you will

meet later in this chapter.) In the following exercise, you will write an instance method for the Point class, called DistanceTo, that calculates the distance between two points.

Write and call instance methods

1.In the Classes project in Visual Studio 2008, add the following public instance method called DistanceTo to the Point class between the constructors and the private variables. The method accepts a single Point argument called other and returns a double.

The DistanceTo method should look like this:

class Point

{

...

public double DistanceTo(Point other)

{

}

...

}

In the following steps, you will add code to the body of the DistanceTo instance method to calculate and return the distance between the Point object being used to make the call and the Point object passed as a parameter. To do this, you must calculate the dif-

ference between the x-coordinates and the y-coordinates.

2.In the DistanceTo method, declare a local int variable called xDiff, and initialize it to the difference between this.x and other.x, as shown here in bold type:

public double DistanceTo(Point other)

{

int xDiff = this.x – other.x;

}

Chapter 7 Creating and Managing Classes and Objects

135

3.Declare another local int variable called yDiff, and initialize it to the difference between this.y and other.y, as shown here in bold type:

public double DistanceTo(Point other)

{

int xDiff = this.x – other.x; int yDiff = this.y - other.y;

}

To calculate the distance, you can use the Pythagorean theorem. Work out the square root of the sum of the square of xDiff and the square of yDiff. The System.Math class

provides the Sqrt method that you can use to calculate square roots.

4.Add the return statement shown in bold type in the following code to the end of the DistanceTo method to perform the calculation:

public double DistanceTo(Point other)

{

int xDiff = this.x - other.x; int yDiff = this.y - other.y;

return Math.Sqrt((xDiff * xDiff) + (yDiff * yDiff));

}

You will now test the DistanceTo method.

5.Return to the Entrance method in the Program class. After the statements that declare and initialize the origin and bottomRight Point variables, declare a variable called distance of type double. Initialize this double variable to the result obtained when you call the DistanceTo method on the origin object, passing the bottomRight object to it as an argument.

The Entrance method should now look like this:

static void Entrance()

{

Point origin = new Point();

Point bottomRight = new Point(1024, 1280); double distance = origin.DistanceTo(bottomRight);

}

Note IntelliSense should display the DistanceTo method when you type the period character after origin.

6.Add to the Entrance method another statement that writes the value of the distance variable to the console by using the Console.WriteLine method.

The completed Entrance method should look like this:

static void Entrance()

{

Point origin = new Point();

Point bottomRight = new Point(1024, 1280);

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]