The Programming Language TIPS
Overload and rewriting
problem
In the daily discussion, the term is not unified to bring a little confusion.
Conventional expression
OverLoad overload function name, different parameters (strict definitions) Static resolution Override rewrite (overwriting, overwriting, rewriting) Subclass redefines the false parent class defined virtual function (individual language allows return value, Access level can be different) dynamic resolution
Example
Class base {} class derived: base {} class client {void test (base obj) {console.writeline ("base");} void test (derived obj) {console.writeline ("derived");} static void main (String [] args) {base obj = new derived (); new client (). Test (obj); // output "base"}}
Static constructor
problem
1. In the tool class, some initialization needs to be performed before any static method is called, such as the reading of configuration information.
2. Complex static information in the ordinary class, need to initialize before any instance method
I have seen the solution
1. Call the required initialization in each static method PUBLIC CLASS Someutilclass () {} private static void init () {// ....} public static string getuid () {init (); returni uid;} public static string GetConnectionString () {Init (); return connString;}} 2, the initialization public class SomeMapperClass {private static Hashtable types in the normal constructor; public SomeMapperClass () {if (types == null) {types = new hashtable (); types.add ("red", color.red); types.add ("green", color.green); types.add ("blue", color.blue);}} public color color GetColor (String color) {return (color) types [color];}}
I recommend solution
Use a static constructor (C #), or static initialization block (Java) [C #] public class someclass {init (); types = new hashtable (); typees.add (...); types.add (...);}} [java] public class someclass {static = new hashmap (); types.put (",", "); types.put (", ""); }
effect
1, ONCE, ONLY ONCE
2. There is a requirement for exception processing in the definition.
2, there is a problem when multi-thread, I don't know, discuss it.
Reading agent
problem
There is a collection inside the object, which controls the addition deletion of its element, but the customer needs to access the collection to obtain the information you want, and the object is not possible to provide the corresponding method for all customers, so you need to return to the inside. Collection, but does not allow customers to increase or delete their elements
I have seen the solution
Returns a member reference representing a collection, only in the document, requiring customers to delete the elements in the collection, PUBLIC CLASS; Public List GetAttributes () {Return Attrs}}
I recommend solution
1, the function provided by the preferred language
2, the function provided by the secondary class library
3, pack your own proxy class, or return a depth copy, or use AOP
[C ] class config {public: const list
effect
1, the functionality provided by the language can help check in the compile period, make sure that the program is trying to add an element in the program does not exist; but there is no power to intentionally intertwind.
2, the functionality provided by the class library can help check in the runtime, make sure that the operation of trying to delete the elements in the program throw an exception
Synchronous agent
problem
In order to introduce the synchronization mechanism for the thread safety of the object, the subject has paid unnecessary performance in a single-threaded environment, and the example of writing COW I have ever seen when writing.
It is not seen, don't do anything, use synchronous primitives
[C #] public class SomeClass {[MethodImplAttribute (MethodImplOptions.Synchronized)] public void Add (string name) {attrs.Add (name);}} [Java] public class SomeClass {public synchronized void Add (string name) {attrs. Add (name);}}
I recommend solution
The implementation of the reference library, providing the original class without synchronization, and synchronous proxy class; the early JDK, Vector and HashTable are synchronous class, new ArrayList and havehmap are not synchronized, and Collectes provide static ways to return synchronization Agent; when you need to change the collection in a multi-threaded environment, use the proxy class
[C #, multithreaded "Customer class code] PUBLIC CLASS SOMECLASS {PUBLIC SOMECLASS (IList Source) {attrs = arraylist.synchronized (});} public void add (String name) {attrs.add (name) Public void remove (string name) {attrs.remove (name);}} [c #, single-threaded customer class code] PUBLIC CLASS OtherClass {PUBLIC Class OtherClass (ilist source) {attrs = Source;} Public void add (since) {attrs.add (name);} public void remove (string name) {attrs.remove (name);}} [Java, customer class code using synchronization agent in multi-threaded environment] Public Class SomeClass {public SomeClass (list source) {attrs = collections.synchronizedlist (} public void add (string name) {attrs.add (name);}} [Java, single-threaded customer class code ] Public class otherclass {public odse (List source) {{PUBLIC OTHERCLASS Attrs = source;} public void add (String name) {attrs.add (name);}}
Don't have to pay an extra price for unwanted features
Resource management
problem
Sometimes it takes precise control resource allocation and release, to ensure exception security of resources, avoid resource leakage, resulting in dead lock, file loss, database connection is too much, etc.
I have seen the solution
Try / catch / finally is flooded in the code in the language lack of real local objects and destructors.
Using middleware can help solve some resource management, such as database connections, etc.
AOP-based resource management framework may occur
I recommend solution
In C , automated resource management is later, namely B.S. "Resource Management, Initialization" (RAII)
In C #, you can use using idispose to get approximately RAII effects
In Java, I don't know, discuss it.
[C , RAII, only example, the operation file should prefer std :: fstream, etc.] Class file {public: explicit file (string path) {pf = fopen (path.c_str (), "rwb");} ~ file () {Fclose (PF);} Operator file * () {RETURN PF;} private: file * pf;}; [C , RAII customer code, only example, the operation file should prefer std :: fstream, etc.] void test () {File File ("auto.txt"); char buf [256]; fread (buf, 0, 256, file); // Even if this operation will throw an exception, the file is still turned off} [C #, only example] public class File: IDisposable {private FileStream fs; public File (string path) {fs = new FileStream (path, FileMode.Create);} public static implicit operator FileStream (File file) {return file.fs;} public void Dispose ( ) {Fs.close ();}} [c #, only example] public class test {void test () {using (file file = new file ("auto.txt")) {// Some Read, Write, ETC. } // The file has been turned off, even if an exception is thrown a certain step }} Effect
1. Resource management automation, not limited to memory
2, C uses templates, you can uninforce most resources packages, current C # can only define individual classes for each resource, or use AOP
The virtual function in the constructor
Language characteristics
[C ] The virtual function is related to the object state, regardless of the access rights (PUBLIC / protected / private), as long as the sub-object constructed, you can call the rewrite method, regardless of access [Java, C #] virtual functions and object status Norway, it is possible to call overwritten methods for the access rights permission to access the permission, no matter whether the child object is constructed.
as a result of
[C ] The method called in the base class constructive function / destructor is always the implementation of the base class, and does not adjust to the subclass; in other methods, the virtual function is always transferred to the subclass of overwriting, no matter Is it private [Java, C #] to call the method in the base class constructor, as long as the subclass has written the method, it will be adjusted to the subclass.
Solution
Carefully call virtual functions in the constructor, especially in Java and C #, at least in the comment, for the reasons for interface programming
problem
Although "Programming" is made as a principle, it has been widely circulated, but it is still visible to the interface parameters in practical applications, and returns to the return value.
I have seen the solution
Return the interface with Factory Method and minimize access rights of specific class constructors, or access to class itself
I recommend solution
Factory Method is still worth recommending, and can also use the characteristics of the language itself to avoid writing a Factory Method.
In C , you can change its access rights when Override is a virtual function.
In C #, you can use the "explicit interface member implementation"
In Java, I don't know, discuss it.
[C ] class isomeinterface {public: virtual void someMethod () = 0;}; class someclass: public isomeinterface {private: void someMethod () {std :: cout << "subclass / n";}}; int Main Argc, _tchar * argv []) {someclass obj; obj.SomeMethod (); // error isomeinterface & iobj = obj; iobj.SomeMethod (); // ok return 0;} [c #] public interface isomeinterface {void SomeMethod () PUBLIC CLASS SOMECLASS: ISOMEINTERFACE {// 1, do not write access modifiers; 2, usage full name Void isomeinterface.SomeMethod () {system.console.writeline ("subclass");}}} () {Someclass obj = new someclass (); obj.someMethod (); // error; isomeinterface iobj = obj; iobj.somethod (); // ok}}
effect
1, write less a Factory Method
2, do not need access to the constructor
Resistance and coordination
problem
When the OVERRIDE virtual function, the subclass sometimes wants to return or handle a slightly different types with the parent class function parameters and the return value, such as the "animal class" has a virtual function of "partner", its return value type "Animal class ",,", "The child" Rabbit "OVERRIDE" partner ", you need to change the return value to" rabbit "; suppose" bird "has a virtual function of" eating ", its parameter type is" cereal ", but the subclass When the iron bird "Override" eat ", the parameters need to be changed to" alkaline food "; at this time, in addition to using a generic solution, it is necessary to use the definition of resistance and coarrent definitions.
Resistance: Changes to the direction of the parent class: Change to the direction of the subclass
language support
Return Value Changes and parameter coexes bring obvious type security issues, so commonly used fundamental is the return value coordination and parameter resistance; the most comprehensive EIFFEL supported by anti-change and coastal support is Eiffel, which provides Bunch of pizhu to resolve the type security problem brought by the return value to the parameter coordination
[C ] only supports return value Co-Class Animal {Public: Virtual Animal Const & SPOUSE () = 0;}; Class Rabbit: Public Animal {public: Rabbit const & spouse () {return Rabbit ();}}; [c #] Do not support [Java] 1.5, 1.5 is combined with generic combination, limited support coordination; other for CHECKED Exception, Java supports unusual declaration
[Recommended reference]
1.c # standard: ECMA-334: C # language specification
2.Java standard: The JavaTM Language Specification Second Edition
3.c standard: ISO / IEC 14882: 2003 Programming Languages - C
4.The C # Programming Language
5.The Java Programming Language
6.THE C Programming Language