Multi-inheritance mechanism with attribute simulation

zhaozj2021-02-11  204

Multi-inheritance mechanism with attribute simulation

First, the question is proposed

In a project, if we want to use the window, it is very simple, you can have a window with only a few lines: use system;

Using system.windows.forms;

Namespace WindowsApplication1

{

///

/// A simplest window

///

Public class form1: form {}

}

This is the simplest window, if we want to add something to it, for example, give it a background color, we can do this:

Public Class Yellowform: Form

{

Public Yellowform ()

{

THIS.BACKCOLOR = Color.Yellow;

}

}

If we want a set of background colored windows, you can use YellowForm as the base class, other windows will be inherited from Yellowform inherit: ...

PUBLIC CLASS Class2: Yellowform {}

...

Similarly, we can also do some other modifications to the window. For example, we have to use the mouse to drag the window, you can do this (in order to save space, the specific details): public Class MovableForm: Form

{

Public MovableFormattribute ()

{

this.mousedown = New MouseEventHandler (FormMouseDown);

this.mousemove = new mouseeventhandler (FormMouseMove);

THIS.MOUSEUP = New MouseEventHandler (FormMouseUp);

}

Private Void Formousedown (Object Sender, System.Windows E)

{...}

Private Void Formousemove (Object Sender, System.Windows.Forms.MouseEventArgs E)

{...}

Private void Formouseup (Object Sender, System.Windows E)

{...}

}

The same reason, as long as we can use MovableForm as just as using Yellowform. However, if we want to use Yellowform, what do you want to use MovableForm?

Second, the problem of the problem

If we can use Yellowform and MovableForm: Public Class Class2: Yellowform, MovableForm {}

How good! However, this is unrealistic, C # does not support more inheritance - the earth people know.

However, C # provides a good mechanism-attribute (Attribute). With it, we may use POLICY as "C Design New Think" to use Yellowform and MovableForm as used as POLICY:

[Yellowform] [MovableForm] public class class1: form {}

In this way, even if we want to add other features to the window, you can only add an attribute without having to modify any other code. Ok, let us work hard in this direction.

Third, the solution process

Below, we take Yellowform as an example to find ways to solve this problem.

At this point, YELLOWFORM has become an attribute, then at least its definition should be this: public class yellowformattribute: attribute {}

So, where should the properties of forming the form should be done? If the properties can be like

[YELLOWFORM (THIS)]

In this way, the problem can be simple. It is often ideal and reality that there is a gap-attribute when using this keyword. Therefore, we can only add a method to modify the Formattribute:

Public Interface iPlunge

{

Void PLUNGE (FORM OWNER);

}

Public Class YellowFormattribute: Attribute, iPlunge

{

Public void Plunge (Form Owner)

{

Owner.backcolor = color.yellow;

}

}

The PLUNGE method is a public method for all such Attribute, so we can put it in an interface. At the same time, the problem is coming - where should I call the PLUNGE method? Is it in the constructor? It is impossible, because we have already said before, we can't use this instance of the form of Form as an attribute as a parameter. However, we don't want to call this method like this:

[Yellowform]

[MovableForm]

Public Class Class1: Form

{

Public class1 ()

{

Foreach (Attribute Attr in)

THIS.GETTYPE (). getcustomattributes (typeof (iPlunge), true)

{

IPlunge Plunge = attr as iplunge;

PLUNGE.PLUNGE (THIS);

}

}

}

If this is done, it violates the original intention of our design - only add or delete attributes without modifying any code. However, through the above code, we can naturally think - add a layer between Form and Class1! In this way, we can transfer the code that needs to be performed in the constructor of the Class1 to the new intermediate layer. So we can write such a class:

Public Class formex: Form

{

Public formex ()

{

PLUNGE ();

}

Private void Plunge ()

{

Foreach (Attribute Attr in)

THIS.GETTYPE (). getcustomattributes (typeof (iPlunge), true)

{

IPlunge Plunge = attr as iplunge;

PLUNGE.PLUNGE (THIS);

}

}

}

So, our ideal solution is born, we only need this to use the various window characteristics of our customized:

[Yellowform] [MovableForm] Public Class Class1: formex {}

Fourth, summary

In order to achieve various features to the window, we use the attribute to simulate multi-inheritance mechanism. We can extend this method into other similar applications to make it a solution. In order to adapt to the general application, we must also make some modifications to the above code, so that they can be more common, the main thing is - we should modify the iPluNge interface, making it more general:

Public Interface iPlunge

{

Void PLUNGE (Object Obj);

}

After the IPLUNGE is modified, for the generalized application, we should do a little change when writing the XXXattribute class. Take the above YELLOWFORMATTRIBUTE as an example, we should change the PLUNGE method to:

Public void Plunge (Object Obj)

{

Form Owner = OBJ AS Form;

Owner.backcolor = color.yellow;

}

As long as this is a built-in conversion, convert the object type to what we hope.

In this way, we can use properties to simulate more inherited.

转载请注明原文地址:https://www.9cbs.com/read-3829.html

New Post(0)