建構子- 維基百科,自由的百科全書
文章推薦指數: 80 %
Java
建構子
維基百科,自由的百科全書
跳至導覽
跳至搜尋
在類別基礎的物件導向程式設計中,建構子(英語:Constructor,有時簡稱ctor),別稱:構造方法、建構式、建構子、建構式)是一個類別裡用於建立物件的特殊子程式。
它能初始化一個新建的物件,並時常會接受參數用以設定實例(英語:Instance(computerscience))變數。
建構子跟一般的實例方法十分相似;但是與其它方法不同,建構子沒有回傳型別(英語:Returntype),不會被繼承,且不會有範圍修飾詞。
建構子的函式名稱一般與它所屬的類別的名稱相同。
它承擔著初始化物件資料成員並建立類不變象的任務;在類別不變象無效的時候它會失敗。
一個正確編寫的建構子會使它生成的物件保持在一個有效狀態。
不可變物件必須在建構子內完成所有初始化。
多數程式語言允許建構子多載 -一個類別被允許擁有多個接受不同參數(英語:Parameter(computerprogramming))種類的建構子同時存在。
一些程式語言允許某些特殊種類的建構子。
使用單個類別來具體地建立和返回新實例的建構子,時常被抽象為工廠方法 -一種同樣用來建立新物件,但會同時使用多個類別,或者一些諸如物件池的分配方案來完成這一過程的子程式。
目次
1種類
1.1參數化構造器
1.2預設構造器
1.3轉換建構子
1.4複製建構子
1.5移動建構子
2語法
3內存機制
4語言細節
4.1Java
4.2VisualBasic.NET
4.3C#
4.3.1C#靜態建構子
4.4C++
4.5F#
4.6Eiffel
4.7CFML
4.8ObjectPascal
4.9Perl
4.10PerlwithMoose
4.11PHP
4.12Python
4.13Ruby
5注釋
6參見
7參考來源
種類[編輯]
參數化建構子[編輯]
接收參數的建構子被稱為參數化建構子。
參數的數量可以大於或等於一。
例如,在C++中:classExample
{
intx,y;
public:
Example();
Example(inta,intb);//Parameterizedconstructor
};
Example::Example()
{
}
Example::Example(inta,intb)
{
x=a;
y=b;
}
使用參數化建構子聲明物件時,必須傳入初始值作為建構子的參數。
在這種情況下,一般的聲明物件的方法可能不再適用。
建構子函式的呼叫方式可以分為顯式和隱式兩種。
Examplee=Example(0,50);//Explicitcall
Examplee(0,50);//Implicitcall
預設建構子[編輯]
如果在編寫一個可實例化的類時沒有專門編寫建構子,多數程式語言會自動生成預設建構子。
預設建構子的特性依不同語言而定。
某些情況下它會將所有的實例變數同時初始化到0,或者任何其他別的值;某些預設建構子什麼也不會做。
某些語言(Java,C#,VB.NET)會預設構造由該類類型定義的陣列,使其充滿空值參照。
沒有空值參照的語言一般會禁止預設構造包含不可預設構造物件的陣列,或者要求在建立時專門初始化這些數值 (C++):#include
[1]
複製建構子[編輯]
複製建構子(英語:Copyconstructor)是C++程式語言中的一種特別的建構子,習慣上用來建立一個全新的物件,這個全新的物件相當於已存在物件的副本。
這個建構子只有一個參數(引數):就是用來複製物件的參照(常用const修飾)。
建構子也可以有更多的參數,但除了最左第一個參數是該類別的參照類別型外,其它參數必須有預設值。
移動建構子[編輯]
移動建構式(英語:Moveconstructor)是C++11中新增的一種建構式,用來避免多餘的分配新記憶體——複製——銷毀舊記憶體的操作。
參見C++11條目內的介紹。
語法[編輯]
Java,C++,C#,ActionScript 和 PHP4 中的命名規範會要求建構子函式的名稱與它所在類的名稱相同。
PHP5建議的建構子函式名稱為 __construct。
為了保證向下相容,__construct 方法無法找到時會呼叫任何跟類名同名的方法作為建構子。
從PHP5.3.3起,這種途徑只對非命名空間的類有效。
[2]
在 Perl 裡,建構子被約定俗成地命名為 "new",並且會完成建立物件的大量工作。
在Perl的Moose物件系統中,建構式(叫做new)是自動生成的,程式設計師可以通過指定一個BUILD方法來對其進行擴充。
在VisualBasic.NET 裡,建構子被命名為 New,是個Sub。
Python 裡建構子的被分為__new__和__init__兩個方法。
__new__ 方法負責為實例分配內儲存空間,並接受自身的類作為參數(一般命名為cls)。
__init__ 方法接受被新建的實例作為參數(一般稱為self[3])。
ObjectPascal的建構式用關鍵字constructor標識,並且可以起任意名字(但一般來說會被起名為Create)。
Objective-C的建構式分成兩個方法,alloc和init。
alloc方法分配記憶體,init負責初始化。
new方法會呼叫alloc和init兩者。
記憶體機制[編輯]
在Java,C#和VB.NET裡,建構子會在一種叫做堆積的特殊資料結構裡建立作為參照類型的實例。
數值類型(例如int,double等等)則會建立在叫做堆疊的有序資料結構裡。
VB.NETandC#會允許用 new 來建立值類型的實例。
然而在這些語言-{zh-hant:裡;zh-hans:裡;},即使使用這種方法建立的物件依然只會在堆疊裡。
在C++裡,不用new建立的物件會儲存在堆疊裡,使用new建立時則會在堆積-{zh-hant:裡;zh-hans:裡;}。
它們必須分別使用解構函式或者 delete 操作才能被刪除。
語言細節[編輯]
Java[編輯]
在Java裡,建構子和其他方法的主要差別在於:
建構子不具有任何顯性回傳型別。
建構子無法直接被「new」啟動。
建構子無法被標示為synchronized,final,abstract,native,或者static。
Java裡的建構子會按照以下順序完成下列工作:
將類別變數初始到預設值。
(byte,short,int,long,float,和double變數會預設設為它們相應的0值,booleans會被設為false,chars會被設為空字元('\u0000'),物件參照會被設為null)
參照父類別的建構子,如果沒有定義任何建構子。
將實例變數初始化到指定值。
執行建構子內的程式碼。
在Java中可以通過關鍵詞 super 存取父類別的建構子。
publicclassExample
{
//Definitionoftheconstructor.
publicExample()
{
this(1);
}
//Overloadingaconstructor
publicExample(intinput)
{
data=input;//Thisisanassignment
}
//Declarationofinstancevariable(s).
privateintdata;
}
//Codesomewhereelse
//Instantiatinganobjectwiththeaboveconstructor
Examplee=newExample(42);
不接收任何參數的建構子被稱作「無參數建構子」。
[4]
VisualBasic.NET[編輯]
在VisualBasic.NET中,建構子以"New"為定義方法,並且必須是個Sub。
ClassFoobar
PrivatestrDataAsString
'Constructor
PublicSubNew(ByValsomeParamAsString)
strData=someParam
EndSub
EndClass
'codesomewhereelse
'instantiatinganobjectwiththeaboveconstructor
DimfooAsNewFoobar(".NET")
C#[編輯]
publicclassMyClass
{
privateinta;
privatestringb;
//Constructor
publicMyClass():this(42,"string")
{
}
//Overloadingaconstructor
publicMyClass(inta,stringb)
{
this.a=a;
this.b=b;
}
}
//Codesomewhere
//Instantiatinganobjectwiththeconstructorabove
MyClassc=newMyClass(42,"string");
C#靜態建構子[編輯]
在C#中,靜態建構子是用來初始化任何靜態資料。
靜態建構式也稱為「類建構式」,由於類建構式在生成的MSIL裡名為「.cctor」,因此也被稱為「cctor」。
[5][6]
靜態建構式允許複雜的靜態變數初始化。
[7]
靜態建構式在該類第一次被存取時呼叫,任何使用該類的操作(無論是呼叫靜態函式、屬性還是存取靜態變數,還是構造類別的實例)都會引發靜態建構式的執行。
靜態建構式是執行緒安全的,並且是單例的。
當用在泛型類中時,靜態建構式對於泛型的每個實例化都呼叫一次。
靜態變數也同樣如此。
publicclassMyClass
{
privatestaticint_A;
//Normalconstructor
staticMyClass()
{
_A=32;
}
//Standarddefaultconstructor
publicMyClass()
{
}
}
//Codesomewhere
//Instantiatinganobjectwiththeconstructorabove
//rightbeforetheinstantiation
//Thevariablestaticconstructorisexecutedand_Ais32
MyClassc=newMyClass();
C++[編輯]
C++的建構式以該類別的名稱為標識,且不須寫回傳值型別也無法回傳數值:
classC{
public:
C(void){
...
}
};
建構式的函式體執行是在各個成員構造完之後才開始,因此要想更改成員的建構方法需要使用成員初始化列表:
classB{
public:
std::stringstr;
B(constchar*psz):str(psz){
...
}
};
基底類別的方式與成員相同,是在初始化列表中寫基底類別名、接建構式參數列:
classD:publicB{
public:
D(void):B("Hello,world!"){
...
}
};
複製建構式接受同類物件的左值參照(一般為constT&)、移動建構式接受右值參照(一般為T&&):
classE{
public:
E(constE&e){...}//Copyconstructor
E(E&&e){...}//Moveconstructor
};
C++中,程式設計師若未對某類別定義建構式(以及賦值函式、解構函式),編譯器在滿足條件時會定義相應的函式,參見[8][9][10][11][12][13]等頁面。
F#[編輯]
Eiffel[編輯]
CFML[編輯]
componentinitmethod="Cheese"{
//properties
propertyname="cheeseName";
//constructor
functionCheeseCheese(requiredstringcheeseName){
variables.cheeseName=arguments.cheeseName;
returnthis;
}
}
ObjectPascal[編輯]
programOopProgram;
type
TPerson=class
private
FName:string;
public
propertyName:stringreadFName;
constructorCreate(AName:string);
end;
constructorTPerson.Create(AName:string);
begin
FName:=AName;
end;
var
Person:TPerson;
begin
Person:=TPerson.Create('Peter');//allocatesaninstanceofTPersonandthencallsTPerson.CreatewiththeparameterAName='Peter'
end.
Perl[編輯]
packagePerson;
#InPerlconstructorsarenamed'new'byconvention.
subnew{
#Classnameisimplicitlypassedinas0thargument.
my$class=shift;
#Defaultattributevalues,ifyouhaveany.
my%defaults=(foo=>"bar");
#Initializeattributesasacombinationofdefaultvaluesandargumentspassed.
my$self={%defaults,@_};
#Checkforrequiredarguments,classinvariant,etc.
if(notdefined$self->{first_name}){
die"MandatoryattributemissinginPerson->new():first_name";
}
if(notdefined$self->{last_name}){
die"MandatoryattributemissinginPerson->new():last_name";
}
if(defined$self->{age}and$self->{age}<18){
die"InvalidattributevalueinPerson->new():age<18";
}
#Perlmakesanobjectbelongtoaclassby'bless'.
bless$self,$class;
return$self;
}
1;
PerlwithMoose[編輯]
packagePerson;
#enableMoose-styleobjectconstruction
useMoose;
#firstname(astring)canonlybesetatconstructiontime('ro')
hasfirst_name=>(is=>'ro',isa=>'Str',required=>1);
#lastname(astring)canonlybesetatconstructiontime('ro')
haslast_name=>(is=>'ro',isa=>'Str',required=>1);
#age(Integer)canbemodifiedafterconstruction('rw'),andisnotrequired
#tobepassedtobeconstructor.Alsocreatesa'has_age'methodwhichreturns
#trueifagehasbeenset
hasage=>(is=>'rw',isa=>'Int',predicate=>'has_age');
#Checkcustomrequirements
subBUILD{
my$self=shift;
if($self->has_age&&$self->age<18){#nounder18s
die"Nounder-18Persons";
}
}
1;
PHP[編輯]
classPerson
{
private$name;
publicfunction__construct($name)
{
$this->name=$name;
}
publicfunctiongetName()
{
return$this->name;
}
}
Python[編輯]
>>>classExampleClass(object):
...def__new__(cls,value):
...print("Creatingnewinstance...")
...#Callthesuperclassconstructortocreatetheinstance.
...instance=super(ExampleClass,cls).__new__(cls)
...returninstance
...def__init__(self,value):
...print("Initialisinginstance...")
...self.payload=value
>>>exampleInstance=ExampleClass(42)
Creatingnewinstance...
Initialisinginstance...
>>>print(exampleInstance.payload)
42
Ruby[編輯]
irb(main):001:0>classExampleClass
irb(main):002:1>definitialize
irb(main):003:2>puts"Hellothere"
irb(main):004:2>end
irb(main):005:1>end
=>nil
irb(main):006:0>ExampleClass.new
Hellothere
=>#<0x007fb3f4299118>
注釋[編輯]
參見[編輯]
預設建構式
複製建構子
參考來源[編輯]
^MSDN類別和結構(C++).[2016-05-11].(原始內容存檔於2016-06-16).
^ConstructorsandDestructors(頁面存檔備份,存於網際網路檔案館),fromPHPonlinedocumentation
^Datamodel(頁面存檔備份,存於網際網路檔案館),fromPythononlinedocumentation
^ProvidingConstructorsforYourClasses.OracleCorporation.2013[2013-12-20].(原始內容存檔於2021-12-03).
^FabulousAdventuresinCoding.EricLippert.2013-02-06[2014-04-05].(原始內容存檔於2017-07-07).
^Expert.NET2.0ILAssembler.APress.2006-01-01[2014-04-05].(原始內容存檔於2015-04-14).
^StaticConstructorinC#onMSDN.[2016-03-30].(原始內容存檔於2016-10-30).
^Defaultconstructors.cppreference.[2016-10-29].(原始內容存檔於2020-12-30).
^Copyconstructors.cppreference.[2016-10-29].(原始內容存檔於2020-11-12).
^Moveconstructors.cppreference.[2016-10-29].(原始內容存檔於2021-03-05).
^Copyassignmentoperator.cppreference.[2016-10-29].(原始內容存檔於2021-01-16).
^Moveassignmentoperator.cppreference.[2016-10-29].(原始內容存檔於2020-11-12).
^Destructors.cppreference.[2016-10-29].(原始內容存檔於2021-03-02).
取自「https://zh.wikipedia.org/w/index.php?title=构造器&oldid=73525772」
分類:方法(電腦科學)程式語言比較
導覽選單
個人工具
沒有登入討論貢獻建立帳號登入
命名空間
條目討論
臺灣正體
不转换简体繁體大陆简体香港繁體澳門繁體大马简体新加坡简体臺灣正體
查看
閱讀編輯檢視歷史
更多
搜尋
導航
首頁分類索引特色內容新聞動態近期變更隨機條目資助維基百科
說明
說明維基社群方針與指引互助客棧知識問答字詞轉換IRC即時聊天聯絡我們關於維基百科
工具
連結至此的頁面相關變更上傳檔案特殊頁面靜態連結頁面資訊引用此頁面維基數據項目
列印/匯出
下載為PDF可列印版
其他語言
العربيةБългарскиČeštinaDeutschEnglishEspañolفارسیFrançaisעבריתहिन्दीItaliano日本語한국어LietuviųМакедонскиNederlandsPolskiPortuguêsРусскийSlovenščinaSvenskaதமிழ்УкраїнськаTiếngViệt粵語
編輯連結
0x007fb3f4299118>
延伸文章資訊
- 1定義類別(Class) | Java SE 6 技術手冊 - caterpillar
與類別名稱同名的方法稱之為「建構方法」(Constructor),也有人稱之為「建構子」,它沒有傳回值,建構方法的作用是讓您建構物件的同時,可以同時初始一些必要的 ...
- 2Java :: public/建構式/重載
建構式是與類別名稱同名,無需宣告傳回型態的方法。例如:. public class Some { private int a ...
- 3Day06:爸爸這麼做都是為你好 - iT 邦幫忙
Java SE 系列第6 篇. kirin0127. 1 年前‧ 472 瀏覽. 0. 當我們在定義類別時,有三種東西可以定義,屬性(field)、建構子(constructor)、方法(met...
- 4Java 入門指南- 單元9 - 封裝與建構子 - 程式語言教學誌
檔名:ClassDemo04.java * 作者:張凱慶* 網站:http://kaiching.org */ package classdemo04; public class ClassDe...
- 5Java Constructor 建構子方法的使用 - Java程式教學甘仔店
你是否要在創建時,做一下些事情。 如果沒有也可以不寫Constructor。 例如: 當你沒寫Constructor,也是可以創建類別物件成功。 public class TestDemo ...