2011/12/23

covarience與contravariance千言萬語不如一段程式碼

Covariance(共變性)與contravariance(逆變性)講了半天,有沒有霧茫茫的感覺。
看一段程式碼就明白囉,varience就是不定型別的變數,像VB就是varience,
而傳統的C/C++包含VC++等等都是variable,也就是在編譯時期就決定了資料型態,
Integer就是integer,char就是char。而varience就是在必要時期,例如run-time時才
決定了資料型態,
使用varience的language很多,例如javascript等等。
下面這是由別的地方擷取出來的C#範例。Delegate是很像function point的東東,要先
懂Delegate才能理解covarience與contravariance,
其實我就把他當成函數參考來看,很少人提到這個,所以我也不翻了,就Delegate
四個函數如下:
static object GetObject() { return null; } static void SetObject(object obj)
{ }

static string GetString() { return ""; } static void SetString(string str) {
}

static void Main()
{
// Covariance. A delegate specifies a return type as object,
// but I can assign a method that returns a string.
//英文寫得很清楚 ==> 共變性就是使用delegate時,這個delegate指定傳回一個物件
(或是說varience),但是在statement中卻指定了一個函數是傳回有型別的變數(這邊是
variable)
Func<object> del = GetString;

// Contravariance. A delegate specifies a parameter type as string,
// but I can assign a method that takes an object.
//英文寫得很清楚 ==> 逆變性就是使用delegate時,這個delegate指定傳入一個
variable (這邊是string),但是在statement中卻指定了一個函數是傳入varience(無
型別的變數)
Action<string> del2 = SetObject;

// But implicit conversion between generic delegates is not supported
until C# 4.0.
//不過在下面這個delegate(函數參考)直接的指定,在C#4.0前卻是不合法的。
Func<string> del3 = GetString;
Func<object> del4 = del3; // Compiler error here until C# 4.0.
}

在給一段msdn的程式碼就懂了...
class Mammals{}
class Dogs : Mammals{}
class Program
{
// Define the delegate.
public delegate Mammals HandlerMethod();
public static Mammals MammalsHandler()
{
return null;
}

public static Dogs DogsHandler()
{
return null;
}

static void Test()
{
HandlerMethod handlerMammals = MammalsHandler;

// Covariance enables this assignment.
HandlerMethod handlerDogs = DogsHandler;
}
}
//////////////////////////////////
//contravairence
// Event hander that accepts a parameter of the EventArgs type.
private void MultiHandler(object sender, System.EventArgs e)
{
label1.Text = System.DateTime.Now.ToString();
}

public Form1()
{
InitializeComponent();

// You can use a method that has an EventArgs parameter,
// although the event expects the KeyEventArgs parameter.
this.button1.KeyDown += this.MultiHandler;

// You can use the same method
// for an event that expects the MouseEventArgs parameter.
this.button1.MouseClick += this.MultiHandler;

}

沒有留言:

張貼留言