多態:
某一些事物的多種表現形態
例如人(Person): 男人(man),女人(women)
例如動物(Animal):貓(cat),狗(dog)
1.多態的體現
父類的引用指向了子類對象
2.多態的前提
必須是類與類之間有關係,要麼繼承,要麼實現
3.多態的好處:
大大提高了程序的擴展性,通常還有一個前提,存在覆蓋
4.多態的弊端:
提高了擴展性,但是不能使用的父類的引用訪問父類中的成員
Animal a=new Cat(); //類型轉換 向上轉換
如果想要調用貓的特有方法時,如何操作?
可以強制將父類的引用,轉成子類類型,向下轉型
Cat c=(Cat)a;
c.子類特有方法();
千萬別出現這樣的操作,將父類的對象轉成子類類型,
我們轉換的是父類的引用指向自己子類時,該引用可被提升
,也可以被強制轉換.
Animal a=new Animal();
Cat c=(Cat)a; //這樣是錯誤的
多態自始至終都是子類對象做着變化
instanceOf關鍵字:
判斷某一些類型引用是否指向某一些類型
例如 a instanceOf Cat
5.多態的應用
/*
多態的應用 例子一
基礎班學生: 學習 睡覺
高級班學生: 學習 睡覺(坐着睡覺)
可以將這兩類事物向上抽取,發現功能定義相同,內容不同
*/
class Demo1
{
public static void main(String[] args)
{ /*
Student s=new AdvStudent();
s.study();
s.sleep();
s.function(); //錯誤的, 編譯時看父類引用是否有該方法
*/
method(new BaseStudent());
method(new AdvStudent());
}
public static void method(Student ss){
ss.study();
ss.sleep();
/*使用子類的特有方法要進行判斷,進行強制向下轉換*/
if(ss instanceof BaseStudent){
BaseStudent s=(BaseStudent)ss;
}else if(ss instanceof AdvStudent){
AdvStudent a=(AdvStudent)ss;
a.function();
}
}
}
abstract class Student
{
public abstract void study();
public void sleep(){
System.out.println("躺着睡覺");
}
}
class BaseStudent extends Student
{
public void study(){
System.out.println("學習基礎知識");
}
}
class AdvStudent extends Student
{
public void study(){
System.out.println("學的就業知識");
}
public void sleep(){
System.out.println("哥們是站着睡的");
}
public void function(){
System.out.println("哥有自己的特有方法");
}
}
/*
多態的應用 例子二
接口多態
主板的運行示例
*/
class Demo3
{
public static void main(String[] args)throws Exception
{
MainBoard mb=new MainBoard();
mb.run();
mb.userPCI(new NetCard());//網卡
mb.userPCI(new SoundCard());//聲卡
//三秒主板關閉,電腦結束運行
Thread.sleep(3000);
mb.close();
}
}
/*主板類*/
class MainBoard
{
public void run(){
System.out.println("主板開啓了");
}
public void reset(){
System.out.println("主板重啓了");
}
public void close(){
System.out.println("主板關閉了");
}
public void userPCI(PCI p){ //實現PCI擴展功能
p.open();
p.close();
}
}
/*網卡,聲卡等PCI卡槽*/
interface PCI
{
public abstract void open();
public abstract void close();
}
/*網卡 實現PCI卡槽同一標準f*/
class NetCard implements PCI
{
public void open(){
System.out.println("網卡開啓");
}
public void close(){
System.out.println("網卡關閉");
}
}
/*聲卡卡 實現PCI卡槽同一標準f*/
class SoundCard implements PCI
{
public void open(){
System.out.println("聲卡開啓");
}
public void close(){
System.out.println("聲卡關閉");
}
}
/*
數據庫操作 例子三
假如本來使用jdbc對數據進行操作,然後改用框架高級操作了
只要修改BaseDao的連接 關閉方法即可,
Data Access Object DAO
此代碼不準備運行
*/
class Demo4
{
public static void main(String[] args)
{
new UserDaoImple();// 調用方法進行傳參即可
}
}
class EntityDao
{
private int age;
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
}
class BaseDao
{
//使用jdbc鏈接數據庫
//關閉數據庫鏈接
}
interface UserDao
{
public void add(EntityDao e);
}
class UserDaoImpl implements UserDao
{
public void add(EntityDao e){
BaseDao.開啓數據庫();
//執行add 操作
//Base.closeAll(con,pst,rs); 關閉全部
}
}
6.多態的出現代碼中的特點(多態使用注意事項):
在多態中非靜態成員函數的特點(父類引用指向了子類對象):
在編譯時期,參閱引用類型變量所屬類中是否有該方法,有側編譯通過,
否則,編譯失敗.
簡而言之:非靜態成員函數在多態中,編譯看左邊,運行看右邊
在多態中成員變量的特點:
無論編譯還是運行都是看參考左邊(引用類型所屬的類)
在多態中靜態方法的特點:
無論編譯還是運行都參考左邊
方法區分靜態方法區和非靜態方法區
/*
多態出先在成員中的特點
*/
class Demo2
{
public static void main(String[] args)
{
/*
編譯時期看父類,運行就運行子類的
這個是可以的
Test1 t=new Test2();
t.method_1();
t.method_2();
*/
/*
//編譯時期看父類,運行就運行子類的
//這個是不可以的
Test1 t=new Test2();
t.method_1();
t.method_2();
t.method_3(); //父類沒有這個方法,編譯出錯
*/
/*
//要上訴的編譯運行,需要進行強制轉換
Test1 t=new Test2();
t.method_1();
t.method_2();
Test2 t2=(Test2)t;
t2.method_3();
*/
//new Test3().method_3(); //final方法可以被繼承,不能覆蓋
//靜態成員變量,非靜態成員變量,靜態方法編譯運行都是看左邊
Test1 t= new Test2();
System.out.println(t.num); //輸出的父類引用的num值 即使是static所修飾的
t.method_4(); //static函數輸出的也是父類的內容
System.out.println(t.getN());//沒有重寫輸出的是父類的
}
}
/*
父類 test1
*/
abstract class Test1
{
static int num=3;
private int n=50;
public int getN()
{
return n;
}
public abstract void method_1();
public void method_2(){
System.out.println("fu method_2");
}
public static void method_4(){
System.out.println("fu static");
}
}
/*
test2 繼承 test1
*/
class Test2 extends Test1
{
static int num=30;
private int n=5;
/*
//如果重寫getN() 那麼獲取就是本類的
public int getN()
{
return n;
}
*/
public void method_1(){
System.out.println("zi method_1");
}
public final void method_3(){
System.out.println("zi method_3");
}
public static void method_4(){
System.out.println("zi static");
}
}
/*測試類*/
class Test3 extends Test2
{
}
Object
object是所有父類對象直接 或間接的父類
該類中定義的功能肯定所有對象都具備的功能
equals(Object obj)
指示其他某個對象是否與此對象“相等”。
object類中已經提供與對象是否相同的比較功能.
如果自定義類中也有比較相同的功能,沒有必要重新定義,
只要沿襲父類中的功能建立自己特有的比較的內容即可,就是覆蓋
toString()
返回該對象的字符串表示。通常,toString 方法會返回一個“以文本方式表示”此對象的字符串。
結果應是一個簡明但易於讀懂的信息表達式。建議所有子類都重寫此方法。
hashCode();//object類中的方法, 返回該對象的哈希碼值。
Integer.toHexString();//integet類方法 十進制轉16進制
getClass(); //obejct方法 返回此 Object 的運行時類。
class文件運行一進內存,類就被封裝成對象,所以有一個Class類描述這些class文件
Class中有這些class對象的共性方法,例如名稱,一般方法,構造函數
方法:
getName();
以 String 的形式返回此 Class 對象所表示的實體(類、接口、數組類、基本類型或 void)名稱。
class Demo5
{
public static void main(String[] args)
{
One one=new One();
one.setNum(4);
Two two=new Two();
two.setNum(4);
Three three=new Three();
three.setNum(5);
System.out.println(one.equals(two));
//System.out.println(one.euqals(three));//編譯通過,運行異常
//直接或間接之類都擁有object類的功能,不復寫一樣可以equals
System.out.println(three.equals(two));
System.out.println(two.toString());
System.out.println(three.toString());
}
}
/*
one類要有一個比較的方法,直接複寫equals即可
*/
class One
{
private int num;
public void setNum(int num){
this.num=num;
}
public int getNum(){
return num;
}
/*複寫equals 比較兩個對象的num屬性時候相同*/
public boolean equals(Object obj){
if(!(obj instanceof Two))
throw new RuntimeException("傳入對象類型失敗");
Two t=(Two)obj;
return this.getNum()==t.getNum();
}
}
class Two
{
private int num;
public void setNum(int num){
this.num=num;
}
public int getNum(){
return num;
}
}
class Three
{
private int num;
public void setNum(int num){
this.num=num;
}
public int getNum(){
return num;
}
/*複寫 toString*/
public String toString(){
return this.getClass().getName()+"@"+Integer.toHexString(this.hashCode());
}
}
—————————— ASP.Net+Android+IOS開發、.Net培訓、期待與您交流!——————————