一門課的課后題答案,在這里備份一下:
面向對象程序設計語言
– 比較分析C++、Java、Python、R語言的面向對象特征,這些特征如何實現的?有什么相同點?
C++ 語言的面向對象特征:
對象模型:封裝
(1) 訪問控制機制:
C++提供完善的訪問控制機制,分別是: public,protected和private。
private, public, protected 訪問標號的訪問范圍 |
||
public |
可訪問 |
1.該類中的函數 ; 2.子類的函數; 3.其友元函數訪問;4.該類的對象訪問; |
protected |
可訪問 |
1.該類中的函數;2.子類的函數; 3.其友元函數訪問; |
不可訪問 |
1.該類的對象訪問; |
|
private |
可訪問 |
1.該類中的函數;2.其友元函數訪問; |
不可訪問 |
1.子類的函數;2.該類的對象訪問; |
(2) 對象的獨立性:
C++中對象本身不具有獨立性,也就是對象必須屬於某一個類;
(3) 類本身是不是對象?
C++中類本身不是對象,對象是類的實例化;
(4) 基於類的模型,還是基於對象或原型的模型?
C++是基於類的模型
對象模型:繼承
(1) 類層次結構:采用單根的類層次結構,還是任意的類層次結構?
C++采用任意的類層次結構;
(2) 繼承方式:提供哪些繼承方式?
C++采用三種繼承方式,分別是public繼承,protected繼承,private繼承;
public |
protected |
private |
|
public繼承 |
public |
protected |
不可用 |
protected繼承 |
protected |
protected |
不可用 |
private繼承 |
private |
private |
不可用 |
(3) 采用基於繼承的模型,還是基於指派的模型?
C++是基於繼承的模型
(4) 允許多重繼承?還是只允許單繼承?
C++允許單繼承、多繼承、多重繼承和虛繼承;
在單繼承中,每個類可以有多個派生類,但是每個派生類只能有一個基類,從而形成樹形結構;
C++使用虛擬繼承,解決從不同途徑繼承來的同名的數據成員在內存中有不同的拷貝造成數據不一致問題,將共同基類設置為虛基類。
對象模型:多態
多態:是指同樣的消息被不同類型的對象接收時導致不同的行為。
(1) 類屬:虛函數
用父類的指針指向其子類的實例,然后通過父類的指針調用實際子類的成員函數,這種技術可以讓父類的指針有“多種形態”;
(2) 類屬:模板函數
模板是C++支持參數化多態的工具,使用模板可以使用戶為類或者函數聲明一種一般模式,使得類中的某些數據成員或者成員函數的參數、返回值取得任意類型。
(3) 重載:同名函數
有兩個或多個函數名相同的函數,但是函數的形參列表不同。在調用相同函數名的函數時,根據形參列表確定到底該調用哪一個函數。
C++語言不是“純粹”的面向對象語言:
1) main函數不在任何類里面;
2) 基本的數據類型不是對象;
3) 友元會破壞封裝性;
4) 支持獨立的函數,數據,即過程化編程
變量的語義模型:
C++采用的是值模型,可以創建靜態對象或棧對象;
但只有通過對象引用或指向對象的指針才能實現面向對象的動態約束行為。
C++支持靜態對象和自動對象:
靜態對象:變量定義在函數外或是用static關鍵字修飾的變量存放在靜態存儲區。放在靜態存儲區的數據在整個程序運行期間持續有效。
自動對象:C++默認局部變量的生命期局限於所在函數的每次執行期間。只有當定義它的函數被調用時才存在的對象成為自動對象。自動對象在每次調用函數時創建和撤銷。
C++ 不依賴自動廢料收集(GC):
大多數 OO 語言都依賴於自動存儲回收系統;
C++是例外,其設計目標之一是盡可能避免對自動存儲回收的依賴,以支持系統程序設計,提高效率,減少運行時間上的不確定性。
C++提供靜態約束(默認)和動態約束兩種方式;
C++提供的類類型對象的轉換形式如下:
dynamic_cast<T>(expression): dynamic_cast 主要用來執行“安全向下轉型”(Safe downcasting),也就是用來決定某對象是否歸屬繼承體系中的某個類型;
C++類類型對象的動態轉換機制:
1) 子類向基類的向上轉型(Up Cast)
2) 基類向子類的向下轉型(Down Cast)
3) 橫向轉型(Cross Cast)
Java 語言的面向對象特征:
對象模型:封裝
(1) 訪問控制機制:
Java提供完善的訪問控制機制,分別是: public,protected、friendly和private。
Java類中成員修飾符的訪問權限 |
||||
public |
protected |
friendly |
private |
|
本類 |
√ |
√ |
√ |
√ |
本包 |
√ |
√ |
√ |
× |
子類 |
√ |
√ |
× |
× |
其他 |
√ |
× |
× |
× |
(2) 對象的獨立性:
Java中對象本身不具有獨立性,也就是對象必須屬於某一個類;
(3) 類本身是不是對象?
Java中類本身不是對象,對象是類的實例化;
(4) 基於類的模型,還是基於對象或原型的模型?
Java是基於類的模型;
對象模型:繼承
(1) Java采用單根的類層次結構:
單根層次結構:在Java中,所有類都應從單獨一個基礎類繼承,終級基礎類為“Object”。
(2) 繼承方式:Java只有普通的extends繼承方式
當創建一個類時,總是在繼承,如果沒有明確指出要繼承的類,就總是隱式地從根類Object進行繼承。
(3) 采用基於繼承的模型,還是基於指派的模型?
Java是基於繼承的模型
(4) 允許多重繼承?還是只允許單繼承?
Java中類允許單繼承和多重繼承;
在單繼承中,每個類可以有多個派生類,但是每個派生類只能有一個基類,從而形成樹形結構;
Java中接口允許多繼承;
對象模型:多態
多態:是指同樣的消息被不同類型的對象接收時導致不同的行為。
(1) 類屬:方法覆蓋
覆蓋實現多態性:通過子類對父類的重定義來實 現。方法的參數個數,類型,順序要完全相同。
(2) 重載:同名函數
重載實現多態性:通過在一個類中定義多個同名的方法來實現。方法的參數個數,類型,順序要有所不同。
Java是接近理想的語言,但希望在形式上盡可能靠近常規語言:
1) 不存在全局變量和全局函數;
2) main函數是類的方法;
3) 但,Java中基本數據類型以及類都不是對象。
Java除了基本類型外,變量采用引用模型,因此,Java沒有必要再另外提供引用變量或指針變量機制;
Java支持靜態對象和自動對象;
Java提供自動廢料收集機制(GC);
Java中除了靜態的方法以外,其他所有的方法都采用動態約束;
Java語言的類類型對象的動態轉換機制如下:
向上轉型:子類對象→父類對象
對於向上轉型,程序會自動完成;格式如下:
父類 父類對象=子類實例;
向下轉型:父類對象→子類對象
對於向下轉型,必須明確的指明要轉型的子類類型;格式如下:
子類 子類對象=(子類)父類實例;
Python語言的面向對象特征:
對象模型:封裝
(1) 訪問控制機制:
Python提供的訪問控制機制,分別是: public和private;
Python中,如果函數、類方法和屬性如果以兩個下划線開頭,但是不以兩個下划線結束,它就是private的,其他的一切都是public的。
(2) 對象的獨立性:
Python中對象本身不具有獨立性,也就是對象一定屬於某一個類;
(3) 類本身是不是對象?
Python中類本身是對象;
(4) 基於類的模型,還是基於對象或原型的模型?
Python是基於對象的模型;
對象模型:繼承
(1) 類層次結構:采用單根的類層次結構,還是任意的類層次結構?
Python 2.2版本以后,采用單根的類層次結構;
單根層次結構:所有類是否都應從單獨一個基礎類繼承?
在Python中,所有類都是Object類的子類
(2) 繼承方式:提供哪些繼承方式?
Python采用兩種繼承方式,分別是:
普通繼承方式;
super繼承方式;在super機制里可以保證公共父類僅被執行一次。
(3) 采用基於繼承的模型,還是基於指派的模型?
Python是基於繼承的模型
(4) 允許多重繼承?還是只允許單繼承?
Python允許單繼承、多繼承和多重繼承;
在單繼承中,每個類可以有多個派生類,但是每個派生類只能有一個基類,從而形成樹形結構;
對象模型:多態
多態:是指同樣的消息被不同類型的對象接收時導致不同的行為。
參數傳遞:通過動態束定機制
類屬:通過Self指代對象本身
Python語言不是“純粹”的面向對象語言:
1) 存在全局變量和全局函數;
2) main函數不是類的方法;
3) 但Python一切皆對象。
Python 采用的是引用模型:變量通過引用建立與對象的聯系;
Python支持靜態對象和自動對象;
靜態對象
所有語言的全局變量都是靜態對象;
在Python語言中:
使用global聲明全局變量;
用同樣的global語句可以指定多個全局變量,比如: global x, y, z。
Python依賴自動廢料收集(GC);
Python默認采用引用計數來管理對象的內存回收。
當引用計數為0時,將立即回收該對象內存,要么將對應的block標記為空閑,要么返還給操作系統。
Python中所有方法的調用都是根據對象所指向對象的類型來動態的確定(Python變量的語義模型:引用模型)。因此Python所有的方法采用的是動態約束的方式。
類類型對象的動態轉換機制:
Python的類類型對象之間不提供動態轉換機制;而是采用名-值(對象)動態約束機制。
R語言的面向對象特征:
R語言的面向對象系統:
基於S3的面向對象編程
基於S4的面向對象編程
基於RC的面向對象編程
基於R6的面向對象編程
面向對象語言必須具有的基本特征:
封裝、數據抽象、動態綁定、繼承,僅具備上述二個或三個的,不能算是面向對象語言。
基於S3的面向對象編程:
是一種泛型函數的實現方式;
泛型函數是一種特殊的函數,根據傳入對象的類型決定調研哪個具體的方法;
基於S3的面向對象編程,是一種動態函數調用的模擬實現。
由於基於S3的面向對象編程,並未提供封裝機制。
因此,基於S3的面向對象編程不是嚴格意義上的面向對象語言。
基於S4的面向對象編程:
是一種標准的R語言面向對象實現方式;
S4對象有明確的類定義,參數定義,參數檢查,繼承關系,實例化等的面向對象系統的特征。
對象模型:封裝
(1) 類的定義:在基於S4的面向對象系統中,類定義的格式如下:
setClass(Class, representation, prototype, contains=character(),validity, access, where, version, sealed, package,S3methods = FALSE, slots)
類的實例化
對象名<-new("類名",屬性=屬性值,...)
(2) 訪問控制機制:
R語言中基於S4的面向對象系統,沒有提供訪問控制機制;
(3) 對象的獨立性:
R語言中對象不具有獨立性,也就是對象必須屬於某一個類;
(4) 類本身是不是對象?
R語言中基於S4的面向對象系統中,類本身是對象;
(5) 基於類的模型,還是基於對象或原型的模型?
R語言中基於S4的面向對象系統是基於泛函的模型;
對象模型:繼承
(1) 繼承方式:提供哪些繼承方式?
S4有比S3更為嚴格的繼承關系,用contains 參數表示。
其具有單繼承和多重繼承兩種繼承方式;
單繼承
多重繼承
(2) 采用基於繼承的模型,還是基於指派的模型?
R語言基於S4的面向對象系統是基於指派的模型;
R語言基於S4的面向對象系統是基於指派的模型;
對象模型:多態
通過泛函函數,實現方法的多態機制
R語言中的基於S4的面向對象系統,不是“純粹”的面向對象語言:
1) 存在全局變量和全局函數;
2) main函數不是類的方法;
3) 但, R語言中的基於S4的面向對象系統中,一切皆為對象。
R語言中基於S4的面向對象系統,采用引用模型;
R語言中基於S4的面向對象系統支持靜態對象和自動對象;
R語言中基於S4的面向對象系統依賴自動廢料收集機制(GC);
R語言中基於S4的面向對象系統中所有的方法都采用動態約束;
類類型對象的動態轉換機制:
R語言基於S4的面向對象系統中類類型對象之間不提供動態轉換機制;而是采用名-值(對象)動態約束機制。
基於RC的面向對象編程:
1) RC對象系統從底層上改變了原有S3和S4對象系統的設計,去掉了泛型函數;
2) 真正地以類為基礎實現面向對象的特征。
對象模型:封裝
(1) 類的定義
定義的格式如下:
setRefClass(Class, fields = , contains = , methods =, where =, ...)
(2) 訪問控制機制:
R語言中基於RC的面向對象系統,沒有提供訪問控制機制;
(3) 對象的獨立性:
R語言中對象不具有獨立性,也就是對象必須屬於某一個類;
(4) 類本身是不是對象?
R語言中基於RC的面向對象系統中,類本身是對象;
(5) 基於類的模型,還是基於對象或原型的模型?
R語言中基於RC的面向對象系統是基於對象的模型;
對象模型:繼承
(1) 類層次結構:采用單根的類層次結構,還是任意的類層次結構?
R語言基於RC的面向對象系統采用任意的類層次結構;
(2) 繼承方式:提供哪些繼承方式?
R語言基於RC的面向對象系統沿用R4的繼承方式,用contains 參數表示;
其具有單繼承和多重繼承兩種繼承方式;
單繼承
多重繼承
(3) 采用基於繼承的模型,還是基於指派的模型?
R語言基於RC的面向對象系統是基於繼承的模型;
對象模型:多態
多態:是指同樣的消息被不同類型的對象接收時導致不同的行為。
類屬:方法覆蓋
R語言中的基於RC的面向對象系統,接近“純粹”的面向對象語言:
1) 不存在全局變量和全局函數;
2) 但,main函數不是類的方法;
3) R語言中的基於RC的面向對象系統中,一切皆為對象。
R語言中基於RC的面向對象系統,采用引用模型;
R語言中基於RC的面向對象系統支持靜態對象和自動對象;
R語言中基於RC的面向對象系統依賴自動廢料收集機制(GC);
R語言中基於RC的面向對象系統中所有的方法都采用動態約束;
類類型對象的動態轉換機制:
R語言基於RC的面向對象系統中類類型對象之間不提供動態轉換機制;而是采用名-值(對象)動態約束機制。
基於R6的面向對象編程
R6類型非常接近於RC類型(Reference classes),但比RC類型更輕;
由於R6不依賴於S4的對象系統,所以用R6的構建面向對象系統會更加有效率。
對象模型:封裝
(1) 類的定義
在基於R6的面向對象系統中,類的定義和實例化的格式如下:
(2) 訪問控制機制:
R語言中基於R6的面向對象系統,提供的訪問控制機制,包括:public和private兩種類型。
在類中訪問公有成員時,需要使用self對象進行調用。
在類中訪問私有成員變量時,要通過private對象進行訪問。
(3) 對象的獨立性:
R語言中對象不具有獨立性,也就是對象必須屬於某一個類;
(4) 類本身是不是對象?
R語言中基於R6的面向對象系統中,類本身是對象;
(5) 基於類的模型,還是基於對象或原型的模型?
R語言中基於R6的面向對象系統是基於對象的模型;
對象模型:繼承
(1) 類層次結構:采用單根的類層次結構,還是任意的類層次結構?
R語言基於R6的面向對象系統采用任意的類層次結構;
(2) 繼承方式:提供哪些繼承方式?
R語言基於R6的面向對象系統的繼承是通過inherit來實現 ,其具有單繼承和多重繼承兩種繼承方式;
單繼承
多重繼承
(3) 采用基於繼承的模型,還是基於指派的模型?
R語言基於R6的面向對象系統是基於繼承的模型;
對象模型:多態
多態:是指同樣的消息被不同類型的對象接收時導致不同的行為。
類屬:方法覆蓋
R語言中的基於R6的面向對象系統,接近“純粹”的面向對象語言:
1) 不存在全局變量和全局函數;
2) 但,main函數不是類的方法;
3) R語言中的基於R6的面向對象系統中,一切皆為對象。
R語言中基於R6的面向對象系統,采用引用模型;
R語言中基於R6的面向對象系統支持靜態對象和自動對象;
R語言中基於R6的面向對象系統依賴自動廢料收集機制(GC);
R語言中基於R6的面向對象系統中所有的方法都采用動態約束;
類類型對象的動態轉換機制:
R語言基於R6的面向對象系統中類類型對象之間不提供動態轉換機制;而是采用名-值(對象)動態約束機制。
保持更新,資源來源於網絡。