Nanjing University of Posts and Telecommunications Li Jianzhong (Cornyfield@263.net)
Component programming is not discarded on traditional object-oriented, and the opposite component programming is deepening and developing object-oriented programming. As an object-oriented soul, there is a quite extensive application in the C # language. Many very "Sharp" component features are even directly packaged. The depth of the class is naturally an important part of our "Sharp XP".
class
The class of C # is a data structure that includes data members, function members, and nested types. The data member can be a constant, a domain. Function members can be methods, attributes, indexers, events, operators, instance builders, static builders, and destructors. We will analyze these members and their characteristics in detail in the "Fifth Tectors and Designors" and "Sixth Lecture Domain Method Properties and Index". In addition to certain imported external methods, classes and their members in C #, the declarations and implementations are usually put together.
C # uses a variety of modifiers to express different properties of the class. There are five different restriction modifiers based on their protection grade C #:
Public can be accessed arbitrarily; protected can only be accessed by this class and its inheritance subclass; INTERNAL can only be accessed by all classes in this composition (Assembly), and the assembly is a combined logic after the C # language. Units and physical units, their compiled file extensions are often ".dll" or ".exe". Protected Internal Unique combination limits modifiers that can only be accessed by all classes in this composite and these classes of these classes. PRIVATE can only be accessed by this class.
If not nested classes, the class within the namespace or compiler is only used in both PUBLIC and INTERNAL.
The New modifier can only be used in nested classes, indicating hidden in the same name type of the inheritance parent class.
Abstract is used to modify the abstraction class, indicating that the class can only be used as a parent class to inherit without object instantiation. Abstract classes can contain abstract members, but this is not necessary. Abstract cannot be used at the same time as New. Below is a false code of abstract type usage:
Abstract Class A
{
Public abstract void f ();
}
Abstract Class B: a
{
Public void g () {}
}
Class C: B
{
Public override void f ()
{
// Method F Implementation
}
}
Abstract class A contains an abstract method F (), which cannot be instantiated. Class B inherits self-class A, which contains an instance method g (), but does not implement abstract method f (), so it must still be declared as an abstract class. Class C inherits self class B, implement class abstract method f (), so that objects can be instantiated.
Sealed is used to modify classes to seal, preventing this class from being inherited. At the same time, it is meaningless to modify the modification of ABSTRACT and Seales and is also disabled.
Object with this keyword
The distinction between classes and objects is important to we grasp the OO programming. We said that the class is a package of its members, but the package is only the first step in our programming, and the class is subjectized, and the implementation operation on its data is the fundamental of our implementation of the real task. Instantiated objects use myclass myObject = new myclass () syntax, where new semantics will call the corresponding builder. C # All objects will be created on the hosted stack. After instantiation, we call it object, its core feature is a copy of your own unique data member. We are called instance members of the data held by these unique objects. Instead, those who are not held in the unique object We call it static members and declare the Static modifier in the class. Only the statically function member is only known to the statically data member. C # circular data members and function members can only get through the class name, look at the following code:
USING SYSTEM; CLASS A
{
Public int count;
Public void f ()
{
Console.WriteLine (this.count);
}
Public stat String name;
Public static void g ()
{
Console.writeLine (Name);
}
}
Class test
{
Public static void main ()
{
A a a1 = new a ();
A a a one = new a ();
A1.f ();
A1.count = 1;
A2.f ();
A2.count = 2;
A.Name = "CCW";
A.G ();
}
}
We declare two A objects A1, A2. For instance members count and f (), we can only be referenced by A1, A2. For static members, Name and G (), we can only reference type A, instead of A1.NAME, or A1.g ().
In the above program, we see that we use this with this in an instance method f () to reference the variable count. What does this mean here? The THIS keyword references the member of the current object instance. In an instance method, we can also omit this, directly reference Count, actually the semantics of both. If the static member function does not have a THIS pointer. The THIS keyword is generally used to access members from constructor, instance methods, and instance accessors.
In the constructor, this is used to define a member hidden by the same name, for example:
Class Employee
{
Public Employee (String Name, String Alias)
{
THIS.NAME = Name;
THIS.AAS = alias;
}
}
Use this to express this as a parameter to other methods, for example:
CALCTAX (this);
This is indignation when this is declared. For example:
Public int this [int param]
{
get
{
Return array [param];
}
set
{
Array [param] = value;
}
}
System.Object class
All classes in C # are directly or indirectly inherited from the System.Object class, which makes the class in the C # to inherit individual. If we don't explicitly designate inheritance, the compiler defaults to inherit this class inheritance from the System.Object class. The System.Object class can also be indicated by lowercase Object keywords, both of which are completely equivalent. All classes in Natural C # have inherited the public interface of the System.Object class, which is important to understand and master the behavior of C # in C #. Below is the System.Object class represented by the interface:
Namespace System
{
Public Class Object
{
Public Static Bool Equals (Object Obja, Object Objb) {}
Public Static Bool ReferenceEquals (Object Obja, Object Objb) {}
Public Object () {}
Public Virtual Bool Equals (Object Obj) {}
Public Virtual Int getHashcode () {}
Public Type gettype () {}
Public Virtual String Tostring () {}
protected virtual void firmize () {}
Protected Object Memberwiseclone () {}
}
Let's first look at the two static methods of Object Equals (Object Obja, Object Objb), ReferenceEquals (Object Obja, Object Objb), and an instance method equals (Object Obj). Before we explain these two methods, we must first clearly oriented two important equality concepts: the value is equal and reference. The meaning of the value is that their data members are equal to the memory bit. Quote is equal to them point to the same memory address, or their object handle is equal. Quote equal inevitable launch value equal. The value type relationship is equal to the "= =" judgment, the two is equal (the structural type and enumeration type do not define the relationship "= =", we must define itself). For the reference type relationship equal sign "= =" to determine whether the two are referenced. The value type is usually not referenced in C #, which is only used in the unmanaged programming "&" to indirectly determine whether the addresses of the two are equal. Static Method Equals (Object Obja, Object Objb) First check if both objects OBJA and OBJB are null, if so, returns True, otherwise Obja.Equals (OBJB) calls and returns its value. The problem is attributed to an example method equals (Object Obj). The method default is actually {Return this = = Obj;} is to determine whether the two objects are referenced. But we note that this method is a virtual method, and C # recommends that we rewrite this method to determine whether the two objects are no respective. Many types in the Microsoft.Net Framework class library have rewritten this method, such as: system.string (string), System.Int32 (int), etc., but some types have not rewritten this method such as: System .Array, etc., we must pay attention when using it. For reference types, if you do not rewrite instance methods equals (Object Obj), we call it equivalent to this = = Obj, ie, reference is equally judged. All value types (implicit inherited from the System.valuetype class) have rewritten instance methods Equals (Object Obj) to determine whether the value is equal.
Note that the object X, X.Equals (null) returns false, where x is obviously not NULL (otherwise you can't complete the equals () call, the system throws an empty reference error). From here we can also see the reasons for design static methods equals (Object Obja, Object Objb) - If both objects Obja and Objb may be null, we can only use object. Equals (Object Obja, Object Objb) To determine if they are equal, and if we don't rewrite the solids (Object Obj), we are still quote equal results. We can implement interface iComparable (related interfaces we will intend to intend to rewrite the solids (Object Obj) in the "Seventh Telephone Inheritance and Polymorphism").
For value types, instance methods Equals (object obj) should be consistent with the return value of the relationship equal sign "= =", that is, if we rewrite the instance method Equals (Object Obj), we should also overload or define relationships, etc. The "= =" operator, and vice versa. Although the value type (inherited from the System.ValueType class) rewrites Equals (Object Obj), but C # recommends that we rewrive our own value type of instance equals (Object Obj) because the system's system.valuetype Written very inefficient. For reference types, we should rewrite instance methods equals (object obj) to express the value, generally should not overload the relationship equal sign "= =" operator, because its default semantic is to determine the reference equal. Static method ReferenceEquals (Object Obja, Object Objb) Judging whether the two objects are referenced. If the two objects are reference types, then its semantics and no overloaded relationships are the same as the "= =" operator. If the two objects are value type, then its return value must be false.
The example method getHashcode () provides a hash code value for the corresponding type, applied to a hash algorithm or hash table. It should be noted that if we rewritten a type of instance method Equals (Object Obj), we should also rewrite the instance method getHashcode () - this should be, the value of the two objects, etc., their hash code is also Should be equal. The following code is a good example of the previous method:
Using system;
Struct a
{
Public int count;
}
Class B
{
Public int number;
}
Class C
{
Public int integer = 0;
Public Override Bool Equals (Object Obj)
{
C c = obj as c;
IF (c! = null)
Return this.integer == C.INTEGER;
Else
Return False;
}
Public Override Int getHashcode ()
{
Return 2 ^ integer;
}
}
Class test
{
Public static void main ()
{
A A1, A2;
A1.count = 10;
A2 = a1;
//Console.write (A1==A2); no "= =" operator
Console.write (a1.equals (a2)); // true
Console.WriteLine (Object.referenceeequals (A1, A2)); // False
B b1 = new b ();
B b2 = new b ();
B1.NUMBER = 10;
B2.NUMBER = 10;
Console.write (b1 == b2); // false
Console.write (b1.equals (b2)); // false
Console.writeLine (Object.referenceeequals (B1, B2)); // False
B2 = B1;
Console.write (b1 == b2); // true
Console.write (b1.equals (b2)); // true
Console.writeline (Object.referenceequals (B1, B2)); // true
C C1 = New C ();
C C2 = New C ();
C1.INTEGER = 10;
C2.INTEGER = 10; console.write (C1 == C2); // False
Console.write (c1.equals (c2)); // true
Console.WriteLine (Object.referenceequals (C1, C2)); // False
C2 = C1;
Console.write (C1 == C2); // true
Console.write (c1.equals (c2)); // true
Console.writeLine (Object.referenceeequals (C1, C2)); // True
}
}
As we expect, compiler and we will get the following output:
Truefalse
Falsefalsefalse
Truetruetrue
Falsetruefalse
Truetruetrue
The example method gettype () is the same as the semantics of TypeOf, which all determine the runtime type of the object by querying the metadata of the object, and we will explain in detail in "Tenthop" and Mapping.
Example method toString () Returns the string expression of the object. If we don't rewrite the method, the system typically returns the type name as a string.
Protected Finalize () methods have special semantics in C #, we will explain in detail in the "Fifth Tectors and Designors".
Protected MemberWiseClone () method returns a "shadow copy" of the current object, which cannot be rewritten by the subclass. "Shadow Copy" is only a bit copy of the object, which means that the value type variable within the object is copied, and the citation type variable is handled, that is, the copied reference variable will hold The same memory reference. Relative to the depth copy relative to the "shadow copy", it is replicated to the reference type variable, not the handle copy. For example, X is an object containing objects A, B reference, while the object A further contains references to object M. Y is a "shadow copy" of X. Then y will have the same A, B reference. However, for a "depth copy" z of X, it will have references to objects C and D, and a reference to an indirect object N, where c is a copy of A, D is a copy of B, N Is a copy of M. Depth Copy In C # By implementing the Icloneable interface (providing clone () method).
I have made a good pavement for the study of objects and system.object as class, but this is only a small step of our sharp trip, and the object members are initialized, the release of memory references, inheritance and polymorphism, and abnormal processing Waiting for many "Sharp" special skills, let us continue to look forward to the following topics!