面向對象軟件構造(第2版)-第7章 靜態結構: 類 (上)

Examining the software engineering background of our discussion, you have seen the reasons for demanding a better approach to modular design: reusability and extendibility.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

研究我們討論中的軟件工程背景,您已經知道到了需要一個更好的方法來模塊化設計的原因:複用性和擴充性。

 

You have realized the limitations of traditional approaches: centralized architectures limiting flexibility. You have discovered the theory behind the object-oriented approach: abstract data types. You have heard enough about the problems. On to the solution!

您已經意識到了傳統方法的侷限性:集中化的架構限制了靈活性。您已經發現了支持面向對象方法的理論:抽象數據類型。你已經聽夠了相關的疑難雜症。解決方案即將到來!

 

This chapter and the others in part C introduce the fundamental techniques of object-oriented analysis, design and programming. As we go along, we will develop the necessary notation.

C部分中的本章和其它章節介紹了面向對象分析,設計和編程的基本技術。隨着研究地深入,我們將逐步展現所需要的符號。

 

Our first task is to examine the basic building blocks: classes.

我們的第一項任務就是要研究基本的組成部分:類。

 

7.1 OBJECTS ARE NOT THE SUBJECT

7.1 對象不是主題

 

What is the central concept of object technology?

對象技術的核心概念是什麼?

 

Think twice before you answer “object”. Objects are useful, but they are not new. Ever since Cobol has had structures; ever since Pascal has had records; ever since the first C programmer wrote the first C structure definition, humanity has had objects.

在您回答對象之前,請三思。對象是有其作用,但它們並不是新的概念。Cobol有結構Pascal存在紀錄自從第一位C程序員寫出了第一個C結構定義之後,我們就有了對象。

 

Objects remain important to describe the execution of an O-O system. But the basic notion, from which everything in object technology derives, is class, previewed in the preceding chapter. Here again is the definition:

對象依然保持着描述OO統執行的重要性。但是基本的概念卻類(class,在對象技術中所有的一切都起源於它。這在上一章已經介紹過了,這裏重複一下它的定義:

 

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

Definition: class

A class is an abstract data type equipped with a possibly partial implementation.

定義:類

類是一個具有可能部份實現的抽象數據類型。

 

<?xml:namespace prefix = w ns = "urn:schemas-microsoft-com:office:word" />

 

Abstract data types are a mathematical notion, suitable for the specification stage (also called analysis). Because it introduces implementations, partial or total, the notion of class establishes the necessary link with software construction — design and implementation. Remember that a class is said to be effective if the implementation is total, deferred otherwise.

抽象數據類型是一個數學上的概念,適用於規格階段也叫分析階段 因爲它引進了部份或完全實現,所以類的概念建立了軟件構造——設計和實現之間的必然聯繫。記住,如果實現是完全的,類被認爲是有效的,否則爲延期的。

 

Like an ADT, a class is a type: it describes a set of possible data structures, called the instances of the class. Abstract data types too have instances; the difference is that an instance of an ADT is a purely mathematical element (a member of some mathematical set), whereas an instance of a class is a data structure that may be represented in the memory of a computer and manipulated by a software system.

就象ADT,類是一個類型:它描述了一套可能的數據結構集合,稱爲類的實例instances)。抽象數據類型也有實例;不同之處是一個ADT的實例是一個純粹的數學元素某些數學集合的成員,而一個類的實例是一個數據結構,其被描述在計算機的內存中,並被軟件系統操作。

 

For example if we have defined a class STACK by taking the ADT specification of the previous chapter and adding adequate representation information, the instances of that class will be data structures representing individual stacks. Another example, developed in the rest of this chapter, is a class POINT modeling the notion of point in a two dimensional space, under some appropriate representation; an instance of that class is a data structure representing a point. Under one of the representations studied below, the cartesian representation, each instance of POINT is a record with two fields representing the horizontal and vertical coordinates, x and y, of a point.

例如,如果採用上一章節中的ADT規格並加入充分的表示法信息,我們定義了一個類STACK那麼類的實例將是代表着獨立棧的數據結構。在本章下面所用的另一個例子是一個類POINT,在適當的表示法之下模擬了二維空間中點的概念;那個類的實例是一個代表點的數據結構。在下面要學習的兩個表示法之一的笛卡爾表示法之中,每個POINT的實例是一個有着兩個字段的紀錄,這兩個字段表示了一個點的水平和垂直座標xy

 

The definition of “class” yields as a byproduct a definition of “object”. An object is simply an instance of some class. For example an instance of class STACK — a data structure representing a particular stack — is an object; so is an instance of class POINT, representing a particular point in two-dimensional space.

義產生了一個副產物:對象義。一個對象只是某個類的一個實例例如一個STACK——表示一個特殊棧的數據結構——的實例是一個對象;而一個POINT的實例代表了維空間中的一個特殊點。

 

The software texts that serve to produce systems are classes. Objects are a run-time notion only: they are created and manipulated by the software during its execution.

用於生成系統的軟件代碼是類。對象只是一個運行時的概念:它們在軟件的執行期間被創造和操縱。

 

The present chapter is devoted to the basic mechanisms for writing software elements and combining them into systems; as a consequence, its focus is on classes. In the next chapter, we will explore the run-time structures generated by an object-oriented system; this will require us to study some implementation issues and to take a closer look at the nature of objects.

本章致力於編寫軟件元素並使之成爲系統的基本機制;作爲結果,它的焦點在類上。在下一章中,我們將探索麪向對象系統所生成的運行時結構;這將要求我們學習一些實現的議題,並進一步瞭解對象的本質。

 

7.2 AVOIDING THE STANDARD CONFUSION

7.2 避免一般性的混亂

 

A class is a model, and an object is an instance of such a model. This property is so obvious that it would normally deserve no comments beyond the preceding definitions; but is has been the victim of so much confusion in the more careless segment of the literature that we must take some time to clarify the obvious. (If you feel that you are immune to such a danger, and have avoided exposure to sloppy object-oriented teaching, you may wish to skip this section altogether as it essentially belabors the obvious.)

一個類是一個模型,一個對象就是這個模型的一個實例。這個屬性如此的明顯,以至於它通常不需要在先前的定義之外再解釋一番;但是它曾經是在許多草率的文獻中引發諸多混亂的受害者,我們必須要花一些時間來澄清這個顯而易見的事情。如果您認爲您不會受到這種危險的感染,並且不想暴露在這種面向對象的喋喋不休的教誨之下,由於它基本上就是在嘲諷,那麼您也許希望完全地跳過這個部

 

What would you think of this?

您意下如何?

 

Among the countries in Europe we may identify the Italian. The Italian has a mountain chain running through him North-South and he likes good cooking, often using olive oil. His climate is of the Mediterranean type, and he speaks a beautifully musical language.

在歐洲的國家中,我們可以識別意大利人。意大利有一個貫穿南北的山脈,他喜歡精美的食物,常常使用橄欖油。他的氣候是地中海類型,並操着一種優美的具有旋律的語言。

 

If someone in a sober state talked or wrote to you in this fashion, you might suspect a new neurological disease, the inability to distinguish between categories (such as the Italian nation) and individuals members of these categories (such as individual Italians), reason enough to give to the ambulance driver the address of Dr. Sacks’s New York clinic.

如果有人在清醒的狀態下用這種方式和您交談話或寫信給您,您也許懷疑一個新的神經病人,他喪失了在範疇如意大利國家這些範疇中的獨立個體獨立的意大利人之間的區別能力,有足夠的原因把他交給救護車司機送往Dr. Sacks紐約診所。

 

Yet in the object-oriented software literature similar confusions are common. Consider the following extract from a popular book on O-O analysis, which uses the example of an interactive system to discuss how to identify abstractions:

在面向對象的軟件文獻中有着相似的混亂。看看從一本流行的OO分析的書中摘取的一段,它使用了一個交互式系統的例子來談論如何辨別抽象:

 

[W]e might identify a “User” Object in a problem space where the system does not need to keep any information about the user. In this case, the system does not need the usual identification number, name, access privilege, and the like. However, the system does need to monitor the user, responding to requests and providing timely information. And so, because of required Services on behalf of the real world thing (in this case, User), we need to add a corresponding Object to the model of the problem space.

我們可以在一個問題空間中識別一個“用戶”對象,這個空間中的系統並不需要保持用戶的任何信息。在這種情況下,系統並不需要通常使用的識別碼,姓名,使用權限等等。然而,系統需要監控用戶,響應請求並提供及時的信息。因此,因爲所請求的服務代表了真實世界的東西(這裏是用戶),所以我們需要加上一個相應的對象來模擬問題空間。

 

In the same breath this text uses the word objects, user and thing in two meanings belonging to entirely different levels of abstraction:

這段文本同時用對象事情來表達二個含意,而這二個含意屬於完全不同的抽象層次:

 

• A typical user of the interactive system under discussion.

·一個討論中的交互系統的典型用戶。

 

• The concept of user in general.

·通常意義上的用戶概念

 

Although this is probably a slip of terminology (a peccadillo which few people can claim never to have committed) rather than a true confusion on the authors’ part, it is unfortunately representative of how some of the literature deals with the model-instance distinction. If you start the study of a new method with this kind of elementary mix-up, real or apparent, you are not likely to obtain a rational approach to software construction.

雖然這有可能只是一個術語(一個小小的過失,很少有人能聲稱不會犯這樣的錯誤)上的筆誤而不是作者造成的真正混亂,但是這不幸地代表了某些文獻如何處理模型-實例的差別。如果您用這種真正的或貌似的概念混合在一起來開始一個新方法的研究,那麼您不可能得到一種軟件構造的合理方法。

 

The mold and the instance

模型和實例

 

Take this book — the copy which you are currently reading. Consider it as an object in the common sense of the term. It has its own individual features: the copy may be brand new, or already thumbed by previous readers; perhaps you wrote your name on the first page; or it belongs to a library and has a local identification code impressed on its spine.

拿起本書——您當前正在閱讀的拷貝。把它視爲常規術語中的一個對象。它有它自己獨立的特性:拷貝也許是全新的,或者上一個讀者已經翻閱過了;或許您在扉頁上籤了您的名字;或是它屬於圖書館並且在書脊上印着標識碼。

 

The basic properties of the book, however, such as its title, publisher, author and contents, are determined by a general description which applies to every individual copy: the book is entitled Object-Oriented Software Construction, it is published by Prentice Hall, it talks about the object-oriented method, and so on. This set of properties defines not an object but a class of objects (also called, in this case, the type of these objects; for the time being the notions of type and class may be considered synonymous).

然而,書的基本屬性,例如它的標題,出版商,作者和內容,取決於應用到每個單獨拷貝上的通用描述:書名爲面向對象軟件構造,它由Prentice Hall出版,它談論面向對象的方法,等等。這些屬性集合定義了不是一個對象,而是對象的一個類(在這種情況中也叫這些對象的類型type);暫時把類型和類兩個概念認爲是同義詞)。

 

Call the class OOSC. It defines a certain mold. Objects built from this mold, such as your copy of the book, are called instances of the class. Another example of mold would be the plaster cast that a sculptor makes to obtain an inverted version of the design for a set of identical statues; any statue derived from the cast is an instance of the mold.

把它稱之爲類OOSC。它定義了一個特定的模型。從這個模型中建立的對象,例如您的書的拷貝,叫做類的實例instances)。模型的另一個例子是石膏模型,雕刻家爲設計一套相同的雕像製作出一個倒置的版本;所有從石膏模型中獲得的雕像都是模型的實例。

 

In the quotation from The Name of the Rose which opens part C, the Master is explaining how he was able to determine, from traces of the snow, that Brownie, the Abbot’s horse, earlier walked here. Brownie is an instance of the class of all horses. The sign on the snow, although imprinted by one particular instance, includes only enough information to determine the class (horse), not its identity (Brownie). Since the class, like the sign, identifies all horses rather than a particular horse, the extract calls it a sign too.

C部分的引文The Name of the Rose,導師解釋了他如何能從雪的痕跡中確定Abbot的馬Brownie先前從這裏走過。Brownie是所有馬的類的一個實例。雪上的標記,雖然由一個特殊的實例留下的,但是其包括的信息只能夠用來確定類(馬),而不是它的特徵(Brownie)。由於類就象標誌一樣識別所有的馬而不是一匹特殊的馬,所以節選引文也稱它爲標誌。

 

Exactly the same concepts apply to software objects. What you will write in your software systems is the description of classes, such as a class LINKED_STACK describing properties of stacks in a certain representation. Any particular execution of your system may use the classes to create objects (data structures); each such object is derived from a class, and is called an instance of that class. For example the execution may create a linked stack object, derived from the description given in class LINKED_STACK; such an object is an instance of class LINKED_STACK.

同樣的概念正好適用於軟件對象。您將在您的軟件系統中編寫的就是類的描述,就象類LINKED_STACK描述了在某個表示法中棧的屬性一樣。您的系統中任何特定的執行也許使用了類去創建對象(數據結構);每個這樣的對象都從類中派生出來,稱之爲類的實例(instance)。例如(軟件)執行可能創建了一個鏈接棧的對象,派生於類LINKED_STACK中給定的描述;這樣的對象就是類LINKED_STACK的一個實例。

 

The class is a software text. It is static; in other words, it exists independently of any execution. In contrast, an object derived from that class is a dynamically created data structure, existing only in the memory of a computer during the execution of a system.

類是軟件代碼。它是靜態的;換句話說,它的存在獨立於所有的執行。相反,從類中派生出的對象是一種動態創造的數據結構,僅在系統的執行期間存在於計算機的內存中。

 

This, of course, is in line with the earlier discussion of abstract data types: when specifying STACK as an ADT, we did not describe any particular stack, but the general notion of stack, a mold from which one can derive individual instances ad libitum.

當然,這符合之前的抽象數據類型討論:當指定STACKADT的時候,我們並沒有描述任何特殊的棧,而是棧的一般概念,一個從中可以任意獲得單獨實例的模型。

 

The statements “x is an instance of T” and “x is an object of type T” will be considered synonymous for this discussion.

在這次討論中,xT的實例”和x是類型T的對象”的聲明將被認爲是同義的。

 

With the introduction of inheritance we will need to distinguish between the direct instances of a class (built from the exact pattern defined by the class) and its instances in the more general sense (direct instances of the class or any of its specializations).

隨着繼承的介紹,我們需要區別類的直接實例direct instances(從由類定義的精確模式中構建)和常規意義上的實例(類的直接實例或任何類的特化)。

 

Metaclasses

元類

 

Why would so many books and articles confuse two so clearly different notions as class and object? One reason — although not an excuse — is the appeal of the word “object”, a simple term from everyday language. But it is misleading. As we already saw in the discussion of seamlessness, although some of the objects (class instances) which O-O systems manipulate are the computer representations of objects in the usual sense of the term, such as documents, bank accounts or airplanes, many others have no existence outside of the software; they include in particular the objects introduced for design and implementation purposes — instances of classes such as STATE or LINKED_LIST.

爲什麼許多書和文章混淆類和對象這二個截然不同的概念?原因之一——雖然不是藉口——是單詞對象的感染力,一個日常所用的簡單術語。但這是誤導。就象我們在無縫的討論中已經知道的,雖然OO系統操作的某些對象(類的實例)是對象在術語的通常意義裏的計算機描述,如文件,銀行帳戶或者飛機,但是許多其它的對象沒有脫離軟件而存在;特別是它們包括了爲設計和實現的目的而引進的對象——類的實例,如STATELINKED_LIST

 

Another possible source of confusion between objects and classes is that in some cases we may need to treat classes themselves as objects. This need arises only in special contexts, and is mainly relevant to developers of object-oriented development environments. For example a compiler or interpreter for an O-O language will manipulate data structures representing classes written in that language. The same would hold of other tools such as a browser (a tool used to locate classes and find out about their properties) or a configuration management system. If you produce such tools, you will create objects that represent classes.

對象和類之間混亂的另一個可能來源是在某些情況下我們也許需要把類本身看作對象。這個需要只會出現在特別的環境裏,並且主要與面向對象開發環境的開發者有關。例如一個OO語言的編譯器或解釋器操作着數據結構,這些數據結構代表着編寫在語言中的類。樣地情況出現在其它的工具中例如瀏覽器(一個用來找出類並得到它們屬性的工具或配置管理系統。如果您編寫這樣的工具,您將會創建代表類的對象。

 

Pursuing an analogy used earlier, we may compare this situation to that of a Prentice Hall employee who is in charge of preparing the catalog of software engineering titles. For the catalog writer, OOSC, the concept behind this book, is an object — an instance of a class “catalog entry”. In contrast, for the reader of the book, that concept is a class, of which the reader’s particular copy is an instance.

繼續使用先前用過的類比們可以拿這個情況與負責準備軟件工程書目目錄的Prentice Hall僱員相比較。對於目錄作者,本書OOSC之後的概念是一個對象——目錄條目的實例。相反,對於本書的讀者而言,那個概念是類,讀者的個人拷貝纔是實例。

 

Some object-oriented languages, notably Smalltalk, have introduced a notion of metaclass to handle this kind of situation. A metaclass is a class whose instances are themselves classes — what the Name of the Rose extract called “signs of signs”.

一些面向對象的語言,特別象Smalltalk,引進了元類(metaclass)的概念來處理這類情況。一個元類是一個類,類的實例是類的本身——就是Name of the Rose節選中所說的“標誌的標誌”。

 

We will avoid metaclasses in this presentation, however, since they bring more problems than benefits. In particular, the addition of metaclasses makes it difficult to have static type checking, a required condition of the production of reliable software. The main applications of metaclasses are better obtained through other mechanisms anyway:

然而在這次介紹中,我們將避免元類,由於它們弊大於利。尤其元類的加入使得靜態類型的檢查更加困難,而這個檢查是軟件產品可靠性的必要條件。總之,元類的主要用途可以更好地通過其它的機制中而獲得:

 

• You can use metaclasses to make a set of features available to many or all classes. We will achieve the same result by arranging the inheritance structure so that all classes are descendants of a general-purpose, customizable class ANY, containing the declarations of universal features.

·您可能使用元類來建立一組對大量的或是所有的類都有效的特性。定義一個多用途的,可自定義的類ANY,其包含通用特性的聲明,所有的類都是它的後代,通過使用這樣的繼承結構我們可以達到同樣的效果。

 

• A few operations may be viewed as characterizing a class rather than its instances, justifying their inclusion as features of a metaclass. But these operations are few and known; the most obvious one is object creation — sufficiently important to deserve a special language construct, the creation instruction. (Other such operations, such as object duplication, will be covered by features of class ANY.)

·一些運算也許被看成是類的特徵,而不是類的實例,它們的內容也證實爲一個元類的特性。但是,這些運算並不多且爲人熟知;最明顯的要算是對象創建——其重要性足以把它認爲是一個特殊語言構造,創建指令。(其它的類似運算,如對象複製,將被類ANY的特性所包含。)

 

• There remains the use of metaclasses to obtain information about a class, such as a browser may need: name of the class, list of features, list of parents, list of suppliers etc. But we do not need metaclasses for that. It will suffice to devise a library class, E_CLASS, so that each instance of E_CLASS represents a class and its properties. When we create such an instance, we pass to the creation instruction an argument representing a certain class C; then by applying the various features of E_CLASS to that instance, we can learn all about C.

·這裏還剩下使用元類來獲得一個類的信息,如類瀏覽器所需要的:類的名字,特性列表,父類列表,供應者列表等等。但是對於這些,我們並不需要元類。設計一個庫類E_CLASS就可以滿足了,E_CLASS的每一個實例代表了一個類和其屬性。當我們創建這樣的一個實例的時候,我們給創建指令傳遞一個特定類C爲參數;接着,通過把E_CLASS的各種特性應用到那個實例上,我們能夠知道C的所有一切。

 

In practice, then, we can do without a separate concept of metaclass. But even in a method, language or environment that would support this notion, the presence of metaclasses is no excuse for confusing molds and their instances — classes and objects.

那麼,實際上不用一個單獨的元類概念我們也能做到這一切。但是,即使在一個支持這個概念的方法,語言和環境中,對於造成模型和其實例——類和對象——之間的混亂,元類的出現也不一定是正確的

 

7.3 THE ROLE OF CLASSES

7.3 類的角色

 

Having taken the time to remove an absurd but common and damaging confusion, we may now come back to the central properties of classes, and in particular study why they are so important to object technology.

花費了一些時間來消除一個荒謬但卻普通並具破壞性的混亂,現在我們可以回到類的重要屬性上來,同時要特別地研究爲什麼對對象技術而言它們很重要。

 

To understand the object-oriented approach, it is essential to realize that classes play two roles which pre-O-O approaches had always treated as separate: module and type.

要理解面向對象方法,意識到類扮演了兩個角色是必要的,OO之前的方法總對把兩個角色分開對待:塊和類型。

 

Modules and types

塊和類型

 

Programming languages and other notations used in software development (design languages, specification languages, graphical notations for analysis) always include both some module facility and some type system.

編程語言和用於軟件開發的其它符號設計語言,規格語言,圖形分析符號總是同時包括了某些模塊工具和某些類型系統。

 

A module is a unit of software decomposition. Various forms of module, such as routines and packages, were studied in an earlier chapter. Regardless of the exact choice of module structure, we may call the notion of module a syntactic concept, since the decomposition into modules only affects the form of software texts, not what the software can do; it is indeed possible in principle to write any Ada program as a single package, or any Pascal program as a single main program. Such an approach is not recommended, of course, and any competent software developer will use the module facilities of the language at hand to decompose his software into manageable pieces. But if we take an existing program, for example in Pascal, we can always merge all the modules into a single one, and still get a working system with equivalent semantics. (The presence of recursive routines makes the conversion process less trivial, but does not fundamentally affect this discussion.) So the practice of decomposing into modules is dictated by sound engineering and project management principles rather than intrinsic necessity.

一個模塊是一個軟件分解單元。我們已經在前面的章節中學習過了模塊的種形式,如例程和包。不考慮模塊結構的確切選擇,我們可以把模塊的概念叫作一個語法(syntactic)概念,因爲分解到模塊隻影響軟件代碼的形式,並不影響軟件的功能;則上把任何的Ada程序寫成一個包,或者把任何的Pascal程序寫成一個主程序的確是有可能的。當然沒有人推薦這樣的方法,並且任何出色的軟件開發者都將使用正在採用的語言的模塊工具把他的軟件分解成易於管理的片斷。但是如果我們採取一個象Pascal這樣的現有程序,那麼我們總是可以把所有的模塊合併成一個單獨的模塊,仍然能得到一個具有相同語義的運行系統。遞歸例程的出現使轉換過程更加簡單,但是基本上不影響本次討論。因此分解成模塊的習慣一般由健全的工程和項目管理原則控制而並非本質上的需要。

 

Types, at first sight, are a quite different concept. A type is the static description of certain dynamic objects: the various data elements that will be processed during the execution of a software system. The set of types usually includes predefined types such as INTEGER and CHARACTER as well as developer-defined types: record types (also known as structure types), pointer types, set types (as in Pascal), array types and others. The notion of type is a semantic concept, since every type directly influences the execution of a software system by defining the form of the objects that the system will create and manipulate at run time.

首先,類型是完全不同的概念。 類型是某些動態對象的靜態描述:在軟件系統的執行中被處理的各種各樣的數據元素。類型集合通常包括預定義類型,例如INTEGER CHARACTER 開發者定義的類型:記錄類型(或是結構類型),指針類型,集合類型(如在Pascal中所用),數組類型和其它。類型的概念是一個語義(semantic概念,這是由於通過定義在運行期間系統將創建並且操作的對象形式,每個類型直接地影響軟件系統的執行。

 

The class as module and type

具備塊和類型的類

 

In non-O-O approaches, the module and type concepts remain distinct. The most remarkable property of the notion of class is that it subsumes these two concepts, merging them into a single linguistic construct. A class is a module, or unit of software decomposition; but it is also a type (or, in cases involving genericity, a type pattern).

OO方法中,模塊和類型概念涇渭分明。類概念中最偉大的屬性就是它囊括了這二個概念,把它們合併進了一個單一的語言架構。一個類就是一個軟件分解模塊或者單元但它也是一個類型或是在泛型中的一個類型模式

 

Much of the power of the object-oriented method derives from this identification. Inheritance, in particular, can only be understood fully if we look at it as providing both module extension and type specialization.

面向對象方法的許多能力都同此有關。尤其是,只有在我們把繼承看作是同時提供模塊延伸和類型特殊化的情況下,它才能被充分地瞭解。

 

What is not clear yet is how it is possible in practice to unify two concepts which appear at first so distant. The discussion and examples in the rest of this chapter will answer this question.

仍然不能確定的問題是如何在實踐中把這兩個起初看上去截然不同的概念統一起來。本章下面的討論和例子將回答這個問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章