標籤:
c#為什麼要用new 修飾子類方法
在C#中,在子類中用new修飾一個方法的目的就是在子類中用該方法隱藏父類中對應方法,這樣,對於同一個方法而言,用父類的執行個體對像來調用和用子類的執行個體對象來調用就各不相同,實現了在子類中用子類方法隱藏父類的方法。
現在考慮一種情況,在程式中用子類執行個體化了一個對象,而現在需要調用該對象對應的父類中的已被子類隱藏了的方法,該如何操作?看以下代碼:
class A
{
public int age;
public void f()
{
age++;
...
}
}
class B:A
{
...
public new void f( )
{
}
...
}
...
static void Main()
{
class B b=new B();
...
b.f().
}
在Main中,f方法是對應對class B的方法,而不是class A的f方法。現在有一個需求,執行完了b.f()後,要執行Class A中的f方法。怎麼辦?按照我以前的做法,再執行個體化一個A類對象c,再將b對象中的成員的當前值賦給c,再執行c.f()。這就是我的做法,當類很簡單時,這種方法也不失為一種方法,但當類很複雜時,要完成前述成員賦值工作是件很恐怖的事,甚至是完不成的事。另外,這樣做又產生一個幾乎與b對象完全一產的對象,這就對資源的利用效率來說是非常不利的。
那有沒有更好的方法呢?其實,有一種很妙的方法可完美解決問題,先上代碼:
...
A c=(A)b;
c.f();
不要輕視,一定要仔細看好上面這兩句其貌不揚,古裡古怪的語句,裡邊的道理妙著呢,首先看第一句,
A c=(A)b;
首先要說明的此語句沒有產生新的A類執行個體對象,因為這是淺複製,那c是什麼,c就是一個指向b對象所指向的B類執行個體對象且標識為類A的對象,這話咋就這麼繞呢?換句話說,c是一個引用型變數,類型為class A,變數名為c,引用的標的的是b所引用的標的,這種變數我們稱為父類聲明子類對象引用的變數。
即然c是class A類型的,那麼c.f()當然是執行了父類A中的方法了,而且由b所引用的執行個體對象在執行,現在所有的問題是不是都解決了?
如果你還看不出文中的微妙之中,那實在可能是我沒有說清楚,或許這個道理真的很微妙,不細心還真看不出來。為了便於理解,請看以下代碼:
class Animal
{
public int age;
public void call()
{
Console.WriteLine("I am an animal.I am {0}", age);
}
}
class Cat : Animal
{
public new void call()
{
Console.WriteLine("I am a cat.I am {0}", age);
}
}
public class Program
{
public static void Main()
{
Cat cat = new Cat();
cat.age = 3;
cat.call();
Animal cat2 = (Animal)cat;
cat2.call();
}
}
啟動並執行結果是:
cat2調用call方法顯示其年齡也是3歲,可知cat2指向的正是cat指向的。
總結一下,以上代碼中b和c指向同一個B類對象,但b可執行B類中的所有方法,c可執行A類中被隱藏了方法,對一個子類執行個體對象,可再定義一個父類聲明子類對象引用的變數,就輕鬆調用子類對象的new方法和被new方法隱藏的父類方法了。
為了鞏固一下理解,將以述稍加變化一下,仍是父類聲明子類對象引用的變數的例子。如下:
public static void Main()
{
Animal cat = new Cat();
cat.age = 3;
cat.call();
Cat cat2 =(Cat)cat;
cat2.call();
}
運行結果為:
注意:C#可以定義父類聲明子類對象引用的變數,但不可以反過來定義子類聲明父類對象引用的變數。比如以下代碼是無法通過編譯的。
A a=new A();
B c=(B)a
這也很好理解,執行個體對象是按照父類產生的,其中是肯定沒有子類的東西的。
再總結,只有父類聲明子類對象引用的變數的概念和子類方法new 聲明配合起來,才能實現在子類對象中即可使用新方法代隱藏(代替)父類中的方法,也可方便地使用被隱藏的方法。這也許就是C#中為什麼要用new 修飾子類方法的主要原因。new的這個作用是override無法提供的。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
C#為什麼要用new 修飾子類方法