JAVA與C++的多型異同
將一個方法呼叫同一個方法主體(大多時候為派生類)關聯起來被稱做繫結。在程式執行前進行繫結,由編譯器和連結程式實現稱為前期繫結。
後期繫結:也稱動態繫結(在程式執行過程中動態實現繫結)如果一種語言想實現後期繫結,就必須具有某種機制,以便在執行時能判斷物件的型別,從而呼叫適當的方法。 也就是說,編譯器不知道物件的型別,但是方法呼叫機制能找到正確的方法體,並加以呼叫。後期繫結機制隨程式語言的不同而有所不同。
JAVA中除了static 方法和final方法之外,其他所有的方法都是後期繫結。(也就是說,後期繫結會自動發生)
EX:
//shape/Shape.java
package polymorehism.shape
import static net.arborj.util.Print.* //簡化print的一個工程類
public class Shape{
public void draw(){
print("Shape draw");
}
}
//:shape/ Circle.java
package polymorehism.shape
public class Circle externs Shape{
public void draw(){
print("Circle drwa");
}
}
//shape/ Square.java
package polymorehism.shape
public class Square externs Shape{
public void draw()
{
print("Square draw");
}
}
public class Main{
public static void main(String[] args){
Shape s = new Circle;
s.draw();
}
}
//輸出(子類成員): Circle draw
多型也不適用於屬性。
這裡雖然是一個Shape引用,後期繫結(多型)中呼叫了Circle.draw()方法。 注意Shape類中的draw方法不能是static ,(private或者final)的 ,static方法與類本身關聯,與物件無關,而private方法屬於finnal方法,派生類(也叫匯出類) 不能訪問,實現的重名draw()是一個全新的函式(與基類無關) ,故如果通過基類引用呼叫,只會呼叫基類方法(不能按照我們所期望的來執行。
還有基類中的屬性也不適用於多型。
--------------------JAVA中多型與工廠(factory)
生成工廠類Generator:
public class RandomShapeGenerator{
private Random rand = new rand(47);
public Shape next(){
switch(rand.next(3)){
default:
case 0 :return new Circle();
case 1 :return new Square();
case 2 :return new Triangle();
}
}
}
public class Shapes{
private static RandomShapeGenerator gen = new RandomShapeGenerator;
public static void main(Strings[] args){
Shape[] s= new Shape[9];
for(int i=0;i<9;i++)
{
s[i]=gen.next();
for(Shape shp:s)
{
shp.draw();
}
}
}
}
Shape基類為自它繼承而來的所有匯出類建立了一個公共介面。 RandomShapeGenerator是一個工廠類,它在每次隨機選擇的Shape物件產生一個引用(我們可以通過對工廠類傳遞引數從而通過switch返回我們需要的子類引用)。 因為程式只與基類介面通訊,這樣的程式可擴充套件的,
可以從通用的基類繼承出新的資料型別,從而新增一些新功能。(為基類新增新函式)而那些操縱基類介面的方法不需要任何改動就可以應用於新類。(將改變的事務與未變的食物分離開的)
-----------------------------------------C++中的多型。
先來看跟JAVA相同例子:
class Shape{
public:
void draw();
}
void Shape::draw(){
pirntf("Shape draw");
}
class Circle:public Shape{
public:
void draw();
}
Circle::draw(){
printf("Circle draw");
}
class Square:public Shape{
public:
void draw();
}
Circle::draw(){
prinf("Square draw ");
}
int main()
{
Circle sc1;
Square sc2;
Shape *s[] = {&sc1,&sc2};
for(int i=0;i<2;i++)
{
s[i]->draw();
}
}
//輸出基類成員Shape draw Shape draw
即通過基類指標呼叫的都是基類中定義的函式,派生類中的函式不會被呼叫
C++中的多型依賴於虛函數
虛擬函式必須是非靜態的成員函式。
虛擬函式的宣告只能出現在類定義中的函式原型宣告中,而不能在成員函式實現的時候。
賦值相容規則:在需要基類物件的任何地方都可以使用公有派生類的物件。
1:派生類物件可以賦值給基類物件。
2:派生類對戲那個可以初始化基類的引用。
3:派生類物件地址可以賦值給指向基類的指標。
C++執行時多型滿足三個條件:1,類之間滿足賦值相容規則。2基類中虛擬函式用virtual宣告。
3:由成員函式來呼叫或者通過指標,引用來訪問虛擬函式。
改進:
class Shape{
public:
virtual void draw();
}
void Shape::draw(){
pirntf("Shape draw");
}
class Circle:public Shape{
public:
void draw(); //覆蓋基類的虛擬函式
}
Circle::draw(){
printf("Circle");
}
class Square:public Shape{
public:
void draw(); //覆蓋基類的虛擬函式
}
Circle::draw(){
prinf("Square");
//Shape::draw(); 可以通過這種方式呼叫基類被覆蓋的函式。
}
int main()
{
Circle sc1;
Square sc2;
Shape *s[] = {&sc1,&sc2};
for(int i=0;i<2;i++)
{
s[i]->draw();
}
}
//輸出子類成員:Circle draw , Square draw .
必須要通過指標或者引用來訪問虛擬函式,如果是通過物件名來訪問虛擬函式,則繫結在編譯過程中就可以進行(靜態繫結),而無需在執行過程進行。(
相關文章
- Objective-C 與 C++ 的異同ObjectC++
- C++之new、delete 與malloc、free的異同C++delete
- Java的OO與多型Java多型
- C++和java多型的區別C++Java多型
- Dart 入門 & 與 ts 型別系統的異同Dart型別
- C++編譯期多型與執行期多型C++編譯多型
- session與cookie的異同SessionCookie
- C++的多型C++多型
- C與Java在流程控制上的異同 (轉)Java
- java與php區別或異同(整理、整合)JavaPHP
- 強制型別轉換時的異常處理_java與c++比較型別JavaC++
- Java中Error和Exception的異同以及執行時異常(Runtime exception)與檢查型異常(checked exception)的區別JavaErrorException
- java繼承與多型Java繼承多型
- JSF與Struts的異同JS
- C++多型C++多型
- C++——多型C++多型
- Java中的類繼承與多型Java繼承多型
- [譯] 同中有異的 Webpack 與 RollupWeb
- Java 的多型Java多型
- oracle與infomix異同點Oracle
- Java語言與C++語言的差異總結JavaC++
- C++多型性C++多型
- C++ 多型的實現原理與記憶體模型C++多型記憶體模型
- 深入理解 C++ 中的多型與檔案操作C++多型
- Java 繼承與多型實驗Java繼承多型
- JavaScript中var與let的異同點JavaScript
- 編譯器GCC與Clang的異同編譯GC
- java中的多型Java多型
- Java 中 this 和 super 的用法概述及異同Java
- Java多型Java多型
- C++八股之函式過載與重寫-靜態多型與動態多型C++函式多型
- C++虛擬函式與多型實戰 (轉)C++函式多型
- margin系列之與相對偏移的異同
- 內容管理與知識管理的異同
- Java和C++的基本差異(轉)JavaC++
- 策略模式和模板方法同與異模式
- C++ 多型的實現及原理C++多型
- 執行時異常與一般異常有何異同?