[Reprinted Summary] knowledge about generic base classes

Source: Internet
Author: User

Newlife. xcode uses generic base classes in a large number of places, which were previously confusing and understandable. I have compiled a document before the Spring Festival, summarized the knowledge of generic base classes, and shared it with others.

Most of the content in this article is excerpted from the introduction of xcode and the following two articles, which are just as follows:

Http://www.cnblogs.com/XmNotes/archive/2012/04/23/2466938.html

Http://www.cnblogs.com/zgynhqf/archive/2010/09/28/1837567.html

In the history of. NET development, 2.0 is a milestone version. Among the many new features brought by. NET 2.0, I think generics are the most important. Although generics have been around for many years, even Java has already introduced generics for reference (although syntactic sugar), generic programming methods have not been popularized. On the one hand, because a large number of frameworks are still written in the non-generic era in the past, on the other hand, the generic design model has not been developed and it is time to change. Here is an example to illustrate these two points. If we have written code for network data capturing, we should be familiar with this Code:

1 var request = WebRequest.Create("http://www.cnblogs.com/") as HttpWebRequest;

Or, the same is true:

1 var request = HttpWebRequest.Create("http://www.cnblogs.com/") as HttpWebRequest;

You can think about it. Why do we need to do it every time? Similar situations include:

 

1 var bm = Image.FromFile("e:\\me.jpg") as Bitmap;2 var bm = Bitmap.FromFile("e:\\me.jpg") as Bitmap;

 

I thought about it, but I don't want to understand it. Both of the above statements call the factory method of the parent class and return an instance of a subclass. Obviously, even if you do not understand OCP, you should think intuitively that the implementation of the parent class should not be determined by the quilt class. The predecessors who wrote webrequest and image may also think that it is inappropriate to directly return the subclass instance. Therefore, the return type of the method signature is changed to the parent class. Although such behavior deserves serious contempt. However,. Net programmers are mostly well-rounded and well-rounded, so this problem has not been changed for many years. The ideal design should be like this: each sub-class of the parent class has an independent factory method and returns its own instance. In this way, it was very clumsy before the appearance of generics, but it was worth the candle. However, with generics, it can be precisely implemented.

Taking the image simulation class as an example, the implementation of image and bitmap is as follows:

 1 class Image<T> where T:Image<T>, new() 2 { 3     public string Path { get; set; } 4     public static T FromFile(string path) 5     { 6         return new T() { Path = path }; 7     } 8 } 9 10 class Bitmap:Image<Bitmap>11 {12 13 }

There is no need for the factory method of image itself.

[Example of the X Component generic base class] a generic base class uses its own type as a generic parameter of the generic base class. In 2006, I changed our data ing framework newlife. xcode to the generic base class. I canceled this approach two months later, because it was so strange. In addition, Microsoft did not recommend this method for the materials found on the Internet at that time, on the grounds that the code would become abnormal and obscure.
In 2007, newlife. xcode started to use the generic base class again, and this time it was finally controlled. Therefore, our congestion entity classes are basically: User: entity <user>, log: entity <log>
The user and log "inherit" entity <> the static method findall in it, and the return types are list <user> and list <log>.
In 2009, let's play again:

 

User <t>: entity <t> where T: User <t >{// entity class subject}
User: User <user >{// default object}
User1: User <user1 >{// first extension, such as adding field attributes}
User2: User <user2 >{// type 2 extension, such as adding business logic}

 

Xcode has entered the second generation since v1.2. The key point is the use of the generic base entity <tentity>. In the first generation of xcode, because of the congestion model, Entity classes must be accompanied by a large number of methods. When their return types are Entity classes or object classes, these methods must be implemented in the code of the entity class, which is actually generated by the code generator. In the second generation of xcode, the generic base class technology is introduced. The entity class uses the generic parameter tentity to specify the final return type. When writing a query method, the generic parameter tentity is used for the return type. Therefore, the second-generation object classes only have attributes and indexers, and do not need to generate query and operation methods, because they are all implemented in the generic base classes. In most cases, the base class generic parameter specified by the object class is its own, because it needs to use its own as the return type. However, the xcode development mode is object-oriented, including entity classes. It also hopes to inherit and add some features, which can be implemented by changing generic parameters.

 

Is the anti-pattern of the generic base class bound to the subclass?

 

"Bind subclass generic layer base class", this mode has also been seen in some famous frameworks, such as csla and blogengine. I have also used it in my original write framework. Of course, I personally think it is an anti-pattern, and my colleagues do not necessarily think so. The benevolent sees benevolence and the wise sees wisdom. However, I have suffered many times, so I decided to write it out and share my experiences with you. The generic layer base class of the BIND subclass is used in some places, rather than any place. It is very suitable to use it on the Orm .. Today, we will talk about the theme based on layersupertype and combined with the generic technology. Similarly, it has an important Convention: generic type parameters must be the final subclass. See the following example:

 1 public abstract class EntityBase<T> where T : EntityBase<T>  2 {  3     public int Id { get; set; }  4     //sth else important......    5 }  6 public class User : EntityBase<User>  7 {  8     public string Name { get; set; }  9 } 10 11 public class Article : EntityBase<Article> 12 { 13     public string Title { get; set; } 14 } 

 

As the base class of all entity classes, entitybase provides unified entity templates, conventions, and some general basic implementations. Code reuse based on this base class makes the code of the subclass very simple. The difference between this and general inheritance and general generics is that the parent class is bound to a specific subclass type at runtime. The disadvantage of using this mode is obvious:

1. You cannot directly use the base class for unified processing.

Continuing with the above example, such a design makes it impossible for us to uniformly process all entities. Since the base classes of user and article are actually two different runtime types, I cannot convert them to the same "entity" type. For example:

Entitybase A = new article (); A = new user ();

I can't even use the abstract entitybase class, because to use this class, you must specify a specific subclass, but if I know which specific subclass to use, there is no need to use their base classes. That is to say, there is no entity abstract class at all, and entitybase <t> only serves to reuse code. I don't know if this can be seen as a violation of the OO liskov replacement principle, but it is really intolerable.

2. Unable to directly implement the re-inheritance of Objects

The second problem is the inheritance mechanism. I cannot directly derive from the current entity class !!! I cannot use the following syntax: goodarticle: article. This is because article "tells" the base class entitybase <t> that the type of the bound subclass is article, not goodarticle, this is in conflict with the entitybase design convention "t must be the final subclass! Unable to inherit ...... Inheritance, as one of the three main features of OO, is simply intolerable.

 

Try to bypass these two problems

 

In fact, the two problems mentioned above can be solved technically:

 

1. cannot convert to the base class. The cause of this problem is that there is no "abstraction unrelated to the subclass. We can add the ientity interface for entitybase <t>. In this way, all subclasses can be converted to ientity, so that they can be processed in a unified manner.

 

2. It cannot be inherited. To solve this problem, we need to extract the classes that need to be inherited into a generic base class and a subclass that inherits the null class of this base class. For example:

 

1 public class Article<T> : EntityBase<T> where T : Article<T> 2 { 3     public string Title { get; set; } 4 } 5 6 public class Article : Article<Article> { } 7 8 public class GoodArticle : Article<GoodArticle> { }

Such a solution seems to be feasible, but such a design is unacceptable:

* As a design class library, I only added a one-way parent class dependent subclass, but had to modify the code of the parent class and split it into two classes.

* Otherwise, all classes are directly written as a generic class + an empty subclass method. (Is this design ugly ?)

* The root problem is not solved: toparticle is not an article, but a class with reusable code.

[Understanding of the above questions]

1. For a language feature, you must have a choice, understand its meaning, and know where it is most suitable, rather than simply using it anywhere.

2. user and article are not child classes of the same parent class, because they map tables in the database, and there is no inheritance relationship between tables, only foreign key relationship; the generic constraints prevent developers from specifying a derived class for the object class. that is to say, this is what the framework designer intends to do.

3. generic implementation is the compile-time (static) polymorphism, not the Runtime polymorphism. entitybase <Article> and entitybase <user> are actually two different static types, this is determined by the compiler, and you do not need to wait for the runtime.
Entitybase <t> is called a generic template. Note that there is a suffix "template", while entitybase <user> is called an instance of the generic template entitybase <t>.

 

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.