C#:
1、繼承C#中的類:C#不支持多重繼承,C#類始終繼承自一個基類(如果未在聲明中指定一個基類,則繼承自System.Object)。
派生類繼承基類的語法如下:
using System;
public class Person
{
//這是基類
}
public class Student:Person
{
//這是派生類
}
注:派生類繼承基類時用“:”符號連接,派生類繼承基類的所有非私有成員變量和方法。
2、調用基類的構造函數:
如果對類沒有定義顯式構造函數,則編譯器將提供默認的構造函數,以初始化這些類的成員字段。但是,如果顯式添加了構造函數,就可以有效控制整個構造過程。
示例:
using System;
namespace Jicheng
{
//基類
public class Person
{
public string _name;
public uint _age;
//基類的構造函數
public Person(string name,uint age)
{
this._name = name;
this._age = age;
//打印輸出
Console.WriteLine(_name);
Console.WriteLine(_age);
}
}
//派生類
public class Student:Person
{
private uint _id;
//派生類構造函數並調用基類構造函數用“:base”
public Student(string name,uint age uint id):base(name,age)
{
this._id = id;
Console.WriteLine(_id);
}
}
public class Exercise
{
[STAThread]
static void Main(string[] args)
{
//構造 Student
Student objstudent=new Student(“XYZ”,45,001);
}
}
}
注:派生類通過使用:base()語法可以顯式調用基類的構造函數。在必要的情況下,可以利用它來初始化字段。
關鍵字:override
override關鍵字用語修改方法,具有override關鍵字修飾符的方法是對基類中同名方法的新實現,基類中的同名方法必須聲明爲virtual或abstract類型。給基類中的方法添加virtual關鍵字表示可以在派生類中重寫它的實現。
1、默認的C#方法並非virtual,因此不能重寫。
2、基類方法的可訪問級別並不因重寫它的方法而改變,他們的訪問修飾符相同。
3、new、static和virtual關鍵字不能與override訪問修飾符一同使用
關鍵字:virtual
C#中提供virtual關鍵字,用語將方法定義爲支持多太,用於對一個類中可修改的方法的聲明,這種方法稱爲虛擬方法,字類可以使用override關鍵字自由實現它們各自版本的虛擬方法
語法:
[訪問修飾符] virtual [返回值類型] 方法名稱([參數列表])
{
//虛擬方法的實現
}
1、virtual訪問修飾符不能與static和override等訪問修飾符一同使用
2、調用虛擬方法,在運行時系統會自動檢查,以確定調調用了哪一個實現方法。
關鍵字:new
new訪問修飾符用於顯式隱藏繼承自基類的成員,如果派生類成員與基類成員名稱相同,new會將派生類成員識別爲一個全新成員。
1、在一個方法中同時使用new和override將會出錯。
2、new訪問修飾符的真正目的是爲了隱藏基類方法。
3、如果將一個方法生命爲new,它實際上並沒有隱藏基類方法,並且編譯器也產生了警告,這時應該刪除new。
什麼是抽象類:不能被實例化的類稱爲抽象類,抽象類是派生類的基類。
關鍵字:abstract
語法:
abstract class 類名
{
…………
}
1、一個抽象類可以同時包含抽象方法和非抽象方法。
2、抽象方法只在派生類中真正實現,這表明抽象方法只存放函數原型,不涉及主體代碼,
3、派生自抽象類的類需要實現其基類的抽象方法,才能實例化對象。
4、使用override關鍵子可在派生類中實現抽象方法,經override聲明重寫的方法稱爲重寫基類方法,其簽名必須與override方法的簽名相同。
示例:
using System;
namespace Example_5
{
//抽象類
abstract class ABC
{
//抽象方法
public abstract void Afunc();
}
//派生類
class Derv:ABC
{
//實現抽象類中的抽象方法
public override void Afunc()
{
Console.WriteLine(“實現抽象方法”);
}
}
public class Test
{
static void Main(string[] args)
{
Derv obj=new Derv();
obj.Afunc();
}
}
}
5、基類實現抽象類,則派生類不需要重新實現該抽象類。
6、抽象類並不僅僅只是一種實現技巧,它更代表一種抽象的概念,從而爲所有的派生類確立一種約定。
關鍵字:interface
語法:
修飾符 interface 接口名
{
//接口主體
}
1、一個接口就相當於一個抽象類,但是它不能半喊任何實現方法。
2、接口的每種方法都必須在派生類中實現。
3、接口有時候可以看成是類的模具,它指明一個類該提供哪些內容。
4、接口主體只限於方法、索引器、屬性的聲明。
5、接口中不能包含字段、構造函數和常量等。
6、接口成員是隱式公開的,如果對其顯式指定訪問級別,就會出現編譯器錯誤。
7、在接口中不能實現任何方法,屬性或者索引器。
8、在指定方法時,只需給出返回類型、名稱和參數列表,然後以分號結束。
9、實現接口的語法與實現繼承一樣,都用冒號“:”
示例
interface Icustomer
{
………………
}
public class MyClass: Icustomer
{
………………
}
10、接口中的方法不能重寫,只能實現。
11、
編碼標準:
接口名稱需始終冠以大寫字母I
C#中多重接口的實現,彌補了C#只能單一繼承,不能多重繼承弱點。
語法示例:
public intetface IName
{
void Name();
}
public interface IAge
{
void Age();
}
public class Consoleshow: IAge, IName
{
public void Name()
{
//具體實現
}
public void Age()
{
//具體實現
}
}
如果兩個接口中有完全相同的簽名,那麼可以用“接口名.方法名”的方法顯式的來實現接口。
示例:
public interface Iname
{
void Test();
}
public interface Iage
{
void Test();
}
public Test: Iname, Iage
{
void Iname Test()
{
// Iname藉口的實現
}
void Iage Test()
{
// Iage藉口的實現
}
}
七、接口繼承
通過合併其他接口,也可以新建接口。用於合併接口的語法於繼承的語法非常相似,只是前者可以將多個接口合併成一個。一個類要實現一個接口,必須爲基接口和派生藉口的所有成員編寫代碼。
一。抽象類
有時候,我們可能想要構造一個很抽象的父類對象,它可能僅僅代表一個分類或抽象概念,它的實例沒有任何意義,因此不希望它能被實例化。例如:有一個父類“ 水果(Fruit)”,它有幾個子類“蘋果(Apple)”、“橘子(Orange)”、“香蕉(Banana)”等。水果在這裏僅僅只是作爲一個分類, 顯然水果的實例沒有什麼意義(就好像一個人如果告訴你他買了一些水果但是卻不告訴你是蘋果還是橘子,你很難想象他到底買的是什麼。)。而水果類又要能被子
類化,這就要求我們使用抽象類(abstract class)來解決這個問題。
在java中,通過在class關鍵字前增加abstract修飾符,就可以將一個類定義成抽象類。抽象類不能被實例化。例如:
定義抽象類水果(Fruit)
public abstract class Fruit {
……
}
如果我們試圖用以下語句來獲得一個實例,將無法編譯成功。
Fruit fruit = new Fruit();
而我們仍然可以構造水果類的子類,如:
子類“蘋果(Apple)”
public class Apple extends Fruit {
……
}
子類“橘子(Orange)”
public class Orange extends Fruit {
……
}
這樣就達到我們的目的了。
抽象類除了能象普通類一樣可以擁有一般的屬性和方法,也可以擁有抽象方法(abstract method)。例如:
抽象類“形狀(Shape)”擁有抽象方法draw()。
public abstract class Shape {
……
public abstract void draw();
……
}
抽象方法與抽象的行爲相對應,通常是這個行爲對父對象沒有意義,而子對象有具體動作。例如方法draw()對於類Shape沒有意義,而類 Shape的子類矩形(Rectangle)的方法draw()可以有實際的動作(根據矩形的四個頂點畫出矩形的四個邊),子類圓(Circle)的方法 draw()也可以有實際的動作(根據圓心和半徑畫出圓周)。
抽象類可以有抽象方法也可以沒有抽象方法;但是如果一個類有抽象方法,那這個類只能定義爲抽象類。
如果按照以下代碼類“形狀(Shape)”仍然擁有抽象方法draw(),但沒有定義爲抽象類,將會編譯失敗。
public class Shape {
……
public abstract void draw();
……
}
抽象方法還有一個特點是,它強迫子類要麼仍然保持抽象性(即不具體實現該方法並仍然定義爲抽象類),要麼具體表現出這個方法的行爲(實現具體的動作或者通過拋出UnsupportedOperationException異常來表明不支持該行爲)。這樣也可以強化多態性。
二 接口
下面談談接口(interface)。java語言使用關鍵字interface定義一個接口。接口也是抽象對象,它甚至比抽象類更抽象。接口中的方法都是抽象方法。
一個接口可以繼承其他接口;一個類通過關鍵字implements聲明要實現一個接口,並具體實現接口的方法。
例如:有一個接口InterfaceA,
Java代碼
public interface InterfaceA {
void methodA();
}
類ClassA實現接口InterfaceA。
Java代碼
public class ClassA implements InterfaceA {
public void methodA() {
System.out.println( "methodA of ClassA implements InterfaceA" );
}
}
如果是抽象類實現一個接口,那麼抽象類中可以不具體實現接口的方法(保持其抽象性),而由其子類去實現。
抽象類ClassB實現接口InterfaceA,但是沒有具體實現方法methodA(),
Java代碼
public abstract class ClassBS implements InterfaceA{ }
子類ClassBSub實現接口InterfaceA,但是沒有具體實現方法methodA(),
Java代碼
public class ClassBSub implements InterfaceA{
public void methodA() {
System.out.println( "methodA of ClassBSub the subclass of ClassB" );
}
}
接口和抽象類顯著的共同點是接口和抽象類都可以有抽象方法。
接口和抽象類的不同點有:
(1)抽象類可以有實例變量,而接口不能擁有實例變量,接口中的變量都是靜態(static)的常量(final)。
(2)抽象類可以有非抽象方法,而接口只能有抽象方法。
java允許一個接口繼承多個父接口,也允許一個類實現多個接口,而這樣的多繼承有上面提到的缺點馬?
答案是沒有,這是由接口的抽象性決定的。
正如前面介紹的,在接口中不能有實例變量,只能有靜態的常量,不能有具體的方法(包含方法體),只能有抽象方法,因此也就摒棄了多繼承的缺點。
對於一個類實現多個接口的情況,因爲接口只有抽象方法,具體方法只能由實現接口的類實現,在調用的時候始終只會調用實現類的方法(不存在歧義), 因此不存在多繼承的第二個缺點;而又因爲接口只有靜態的常量,但是由於靜態變量是在編譯期決定調用關係的,即使存在一定的衝突也會在編譯時提示出錯;而引 用靜態變量一般直接使用類名或接口名,從而避免產生歧義,因此也不存在多繼承的第一個缺點。
對於一個接口繼承多個父接口的情況也一樣不存在這些缺點。
請看以下示例。
接口A:
Java代碼
public interface InterfaceA {
int len = 1 ;
void output();
}
接口B:
Java代碼
public interface InterfaceB {
int len = 2 ;
void output();
}
接口InterfaceSub繼承接口A和接口B:
Java代碼
public interface InterfaceSub extends InterfaceA, interfaceB { }
類Xyz實現接口InterfaceSub:
Java代碼
public class Xyz implements InterfaceSub {
public void output() {
System.out.println( "output in class Xyz." );
}
public void outputLen( int type) {
switch (type) {
case InterfaceA.len:
System.out.println( "len of InterfaceA=." +type);
break ;
case InterfaceB.len:
System.out.println( "len of InterfaceB=." +type);
break ;
}
}
public static void main(String[] args) {
Xyz xyz= new Xyz ();
xyz .output();
xyz .outputLen();
}
以上代碼不存在什麼問題,但是如果試圖編寫以下存在衝突的代碼,則會編譯失敗。
Java代碼
Xyz xyz = new Xyz();
int len = xyz.len;
System.out.println(len);