게으름 초기화
Lazy initialization컴퓨터 프로그래밍에서 게으른 초기화는 물체의 생성이나 가치의 계산, 또는 다른 값비싼 과정이 처음 필요할 때까지 미루는 전술이다.개체나 다른 자원의 인스턴스화를 구체적으로 언급하는 일종의 게으른 평가다.
이는 일반적으로 접근자 방법(또는 속성 게이터)을 확장하여 캐시 역할을 하는 개인 구성원이 이미 초기화되었는지 여부를 확인함으로써 이루어진다.있다면 바로 돌려준다.그렇지 않은 경우, 새로운 인스턴스가 생성되어 회원 변수에 배치되고, 처음 사용하기 위해 발신자에게 제 시간에 반환된다.
객체에 거의 사용되지 않는 속성이 있는 경우, 이렇게 하면 시작 속도가 향상될 수 있다.평균 평균 프로그램 성능은 메모리(상태 변수의 경우)와 실행 주기(확인하기 위해) 측면에서 약간 더 나쁠 수 있지만, 객체 인스턴스화의 영향은 시스템의 시작 단계에 집중되지 않고 시간("정렬화")에 분산되므로 중앙값 응답 시간이 크게 향상될 수 있다.
다중 스레드 코드에서 게으르게 초기화된 개체/상태로의 액세스는 레이스 조건에 대한 보호를 위해 동기화되어야 한다.
"레이지 팩토리"
소프트웨어 설계 패턴 뷰에서는 종종 공장 방식 패턴과 함께 게으른 초기화가 사용된다.이것은 다음과 같은 세 가지 아이디어를 결합한다.
- 공장 방법을 사용하여 클래스의 인스턴스(공장 방법 패턴) 생성
- 인스턴스를 지도에 저장하고 동일한 매개변수를 가진 인스턴스의 각 요청에 동일한 인스턴스 반환(멀티턴 패턴)
- 느리게 초기화를 사용하여 개체를 처음 요청할 때 개체 인스턴스화(느린 초기화 패턴)
예
액션스크립트 3
다음은 ActionScript에서 구현된 게으른 초기화를 사용하는 클래스의 예:
꾸러미 예.게으름뱅이. { 공중의 계급 과일 { 사유의 시합을 하다 _typeName:끈; 사유의 정태의 시합을 하다 인스턴스별유형 이름:사전 = 새로운 사전(); 공중의 기능을 발휘하다 과일(typeName:끈):공허하게 하다 { 이._typeName = typeName; } 공중의 기능을 발휘하다 얻다 typeName():끈 { 돌아오다 _typeName; } 공중의 정태의 기능을 발휘하다 getFluentBy유형 이름(typeName:끈):과일 { 돌아오다 인스턴스별유형 이름[typeName] = 새로운 과일(typeName); } 공중의 정태의 기능을 발휘하다 printCurrentTypes():공허하게 하다 { 을 위해 각각 (시합을 하다 과실:과일 에 인스턴스별유형 이름) { // 각 값을 반복한다. 자취를 감추다(과실.typeName); } } } }
기본 사용량:
꾸러미 { 수입하다 예.게으름뱅이.; 공중의 계급 메인 { 공중의 기능을 발휘하다 메인():공허하게 하다 { 과일.getFluentBy유형 이름("바나나"); 과일.printCurrentTypes(); 과일.getFluentBy유형 이름("애플"); 과일.printCurrentTypes(); 과일.getFluentBy유형 이름("바나나"); 과일.printCurrentTypes(); } } }
C
C에서 게으른 평가는 일반적으로 정적 변수를 사용하여 단일 함수 또는 단일 소스 파일 내에서 구현된다.
함수에서:
#include < 현악기>h> #include <stdlib.h> #include <stddef.h> #include <stdio.h> 구조상의 과실 { 마를 뜨다 *이름을 붙이다; 구조상의 과실 *다음에; 인트로 번호를 붙이다; /* 기타회원 */ }; 구조상의 과실 *get_fruit(마를 뜨다 *이름을 붙이다) { 정태의 구조상의 과실 *fruit_list; 정태의 인트로 Seq.; 구조상의 과실 *f; 을 위해 (f = fruit_list; f; f = f->다음에) 만일 (0 == 발을 동동 구르다(이름을 붙이다, f->이름을 붙이다)) 돌아오다 f; 만일 (!(f = 만록의(의 크기(구조상의 과실)))) 돌아오다 NULL; 만일 (!(f->이름을 붙이다 = 걸레질하다(이름을 붙이다))) { 무료의(f); 돌아오다 NULL; } f->번호를 붙이다 = ++Seq.; f->다음에 = fruit_list; fruit_list = f; 돌아오다 f; } /* 예제 코드 */ 인트로 본래의(인트로 argc, 마를 뜨다 *아그브[]) { 인트로 i; 구조상의 과실 *f; 만일 (argc < 2) { 인쇄물(더부룩한, "용도: 과일 이름[...]\n"); 퇴장하다(1); } 을 위해 (i = 1; i < argc; i++) { 만일 ((f = get_fruit(아그브[i]))) { 활자화하다("과일 %s: 숫자 %d\n", 아그브[i], f->번호를 붙이다); } } 돌아오다 0; }
대신 단일 소스 파일을 사용하면 상태를 여러 기능 간에 공유하면서도 관련되지 않은 기능으로부터 숨길 수 있다.
fruit.h:
#ifndef _FULT_INCLINCED_ #define _FULT_INCINCED_ 구조상의 과실 { 마를 뜨다 *이름을 붙이다; 구조상의 과실 *다음에; 인트로 번호를 붙이다; /* 기타회원 */ }; 구조상의 과실 *get_fruit(마를 뜨다 *이름을 붙이다); 공허하게 하다 print_fruit_list(파일 *파일); #endif/* _FULT_INCLINCED_ */
fruit.c:
#include < 현악기>h> #include <stdlib.h> #include <stddef.h> #include <stdio.h> #include "fuilt.h" 정태의 구조상의 과실 *fruit_list; 정태의 인트로 Seq.; 구조상의 과실 *get_fruit(마를 뜨다 *이름을 붙이다) { 구조상의 과실 *f; 을 위해 (f = fruit_list; f; f = f->다음에) 만일 (0 == 발을 동동 구르다(이름을 붙이다, f->이름을 붙이다)) 돌아오다 f; 만일 (!(f = 만록의(의 크기(구조상의 과실)))) 돌아오다 NULL; 만일 (!(f->이름을 붙이다 = 걸레질하다(이름을 붙이다))) { 무료의(f); 돌아오다 NULL; } f->번호를 붙이다 = ++Seq.; f->다음에 = fruit_list; fruit_list = f; 돌아오다 f; } 공허하게 하다 print_fruit_list(파일 *파일) { 구조상의 과실 *f; 을 위해 (f = fruit_list; f; f = f->다음에) 인쇄물(파일, "%4d %s\n", f->번호를 붙이다, f->이름을 붙이다); }
main.c:
#include <stdlib.h> #include <stdio.h> #include "fuilt.h" 인트로 본래의(인트로 argc, 마를 뜨다 *아그브[]) { 인트로 i; 구조상의 과실 *f; 만일 (argc < 2) { 인쇄물(더부룩한, "용도: 과일 이름[...]\n"); 퇴장하다(1); } 을 위해 (i = 1; i < argc; i++) { 만일 ((f = get_fruit(아그브[i]))) { 활자화하다("과일 %s: 숫자 %d\n", 아그브[i], f->번호를 붙이다); } } 활자화하다(" 다음과 같은 과일이 발생했소.\n"); print_fruit_list(뚱뚱하게 굴다); 돌아오다 0; }
C#
.NET Framework 4.0에서 Microsoft는 다음과 같은 기능을 제공했다.Lazy
게으른 짐을 싣는 데 사용될 수 있는 수업아래는 클래스를 게으르게 로드하는 일부 더미 코드 입니다.Fruit
시합을 하다 게으른 과일 = 새로운 게으름뱅이<과일>(); 과일 과실 = 게으른 과일.가치;
그Fruit
여기서 클래스 자체는 아무 것도 하지 않는다, 클래스 변수 _typesDictionary
저장하기 위해 사용되는 사전/지도Fruit
에 의한 예.typeName
.
사용. 시스템; 사용. 시스템.수집; 사용. 시스템.수집.포괄적인; 공중의 계급 과일 { 사유의 끈을 매다 _typeName; 사유의 정태의 신분증<끈을 매다, 과일> _typesDictionary = 새로운 사전<끈을 매다, 과일>(); 사유의 과일(끈 typeName) { 이._typeName = typeName; } 공중의 정태의 과일 GetFulutBy유형 이름(끈을 매다 타자를 치다) { 과일 과실; 만일 (!_typesDictionary.TryGetValue(타자를 치다, 밖으로 과실)) { // 게으른 초기화 과실 = 새로운 과일(타자를 치다); _typesDictionary.추가하다(타자를 치다, 과실); } 돌아오다 과실; } 공중의 정태의 공허하게 하다 모두 표시() { 만일 (_typesDictionary.카운트 > 0) { 콘솔.WriteLine("만든 인스턴스 수 = {0}", _typesDictionary.카운트); 앞을 내다 (키밸류페어<끈을 매다, 과일> kvp 에 _typesDictionary) { 콘솔.WriteLine(kvp.키); } 콘솔.WriteLine(); } } 공중의 과일() { // 샘플 컴파일이 필요함 } } 계급 프로그램 { 정태의 공허하게 하다 메인(끈을 매다[] 아그) { 과일.GetFulutBy유형 이름("바나나"); 과일.모두 표시(); 과일.GetFulutBy유형 이름("애플"); 과일.모두 표시(); // 처음의 기존 인스턴스 반환 // "바나나"를 사용한 과일 생성 시간 과일.GetFulutBy유형 이름("바나나"); 과일.모두 표시(); 콘솔.리딩라인(); } }
게으른 초기화 설계 패턴의 매우 간단한 '빈칸 채우기' 예(유형에는 열거형이 사용됨 제외)
네임스페이스 디자인 패턴래지 이니셜라이제이션; 공중의 계급 레이지팩토리 오브젝트 { //품목의 내부수집 //IDiectionaery를 통해 고유함 확인 사유의 신분증<레이지 오브젝트 크기, 레이지 오브젝트> _LazyObjectList = 새로운 사전<레이지 오브젝트 크기, 레이지 오브젝트>(); //필요한 크기의 이름을 전달하기 위한 방법 //열 통과를 방지하며 앞에 있는 LazyObject의 일부임 공중의 열거하다 레이지 오브젝트 크기 { 없음, 작다, 큰, 더 큰, 거대하다 } //구성될 개체의 표준 유형 공중의 구조상의 레이지 오브젝트 { 공중의 레이지 오브젝트 크기 크기; 공중의 일리스트<인트로> 결과; } //'size' 목록 만들기 사유의 일리스트<인트로> 결과(레이지 오브젝트 크기 사이즈를 맞추다) { 일리스트<인트로> 결과 = 무효의; 바꾸다 (사이즈를 맞추다) { 케이스 레이지 오브젝트 크기.작다: 결과 = CreateSomeSpecificList(1, 100); 부숴뜨리다; 케이스 레이지 오브젝트 크기.큰: 결과 = CreateSomeSpecificList(1, 1000); 부숴뜨리다; 케이스 레이지 오브젝트 크기.더 큰: 결과 = CreateSomeSpecificList(1, 10000); 부숴뜨리다; 케이스 레이지 오브젝트 크기.거대하다: 결과 = CreateSomeSpecificList(1, 100000); 부숴뜨리다; 케이스 레이지 오브젝트 크기.없음: 결과 = 무효의; 부숴뜨리다; 체납: 결과 = 무효의; 부숴뜨리다; } 돌아오다 결과; } //생성할 값비싼 아이템은 아니지만, 요점은 알 수 있다. //필요할 때까지 일부 값비싼 객체의 생성 완료 사유의 일리스트<인트로> CreateSomeSpecificList(인트로 출발하다, 인트로 종지부를 찍다) { 일리스트<인트로> 결과 = 새로운 리스트<인트로>(); 을 위해 (인트로 반격하다 = 0; 반격하다 < (종지부를 찍다 - 출발하다); 반격하다++) { 결과.추가하다(출발하다 + 반격하다); } 돌아오다 결과; } 공중의 레이지팩토리 오브젝트() { //시공자 } 공중의 레이지 오브젝트 GetLazyFactoryObject(레이지 오브젝트 크기 사이즈를 맞추다) { //네, 문맹이고 부정확하다는 것을 알고 있다. 레이지 오브젝트 노굿섬원; //LazyObjectSize를 목록에서 외부로 검색하거나, LazyObjectSize를 생성하여 목록에 추가 만일 (!_LazyObjectList.TryGetValue(사이즈를 맞추다, 밖으로 노굿섬원)) { 노굿섬원 = 새로운 레이지 오브젝트(); 노굿섬원.크기 = 사이즈를 맞추다; 노굿섬원.결과 = 이.결과(사이즈를 맞추다); _LazyObjectList.추가하다(사이즈를 맞추다, 노굿섬원); } 돌아오다 노굿섬원; } }
C++
#include <아이오스트림> #include <지도> #include <끈> 계급 과일 { 공중의: 정태의 과일* 겟프루트(경시하다 찌꺼기::끈을 매다& 타자를 치다); 정태의 공허하게 하다 PrintCurrentTypes(); 사유의: // 참고: 생성자가 정적 GetFuilt 를 사용하도록 강제하는 경우. 과일(경시하다 찌꺼기::끈을 매다& 타자를 치다) : 타이프_(타자를 치다) {} 정태의 찌꺼기::지도를 그리다<찌꺼기::끈을 매다, 과일*> 종류들; 찌꺼기::끈을 매다 타이프_; }; // 정적 찌꺼기::지도를 그리다<찌꺼기::끈을 매다, 과일*> 과일::종류들; // Lazy Factory 메서드, 특정 과일과 연관된 과일 인스턴스 가져오기 // 타입. 필요에 따라 새로운 것을 만든다. 과일* 과일:GetFuilt(경시하다 찌꺼기::끈을 매다& 타자를 치다) { 자동차로 [그럭저럭, 삽입된] = 종류들.본을 뜨다(타자를 치다, 무효의); 만일 (삽입된) { 그럭저럭->둘째 = 새로운 과일(타자를 치다); } 돌아오다 그럭저럭->둘째; } // 예를 들어, 작동 중인 패턴을 보기 위한 목적으로. 공허하게 하다 과일:PrintCurrentTypes() { 찌꺼기::뻐드렁니가 나다 << "한 인스턴스 수 = " << 종류들.사이즈를 맞추다() << 찌꺼기::끝을 맺다; 을 위해 (경시하다 자동차로& [타자를 치다, 과실] : 종류들) { 찌꺼기::뻐드렁니가 나다 << 타자를 치다 << 찌꺼기::끝을 맺다; } 찌꺼기::뻐드렁니가 나다 << 찌꺼기::끝을 맺다; } 인트로 본래의() { 과일::겟프루트("바나나"); 과일::PrintCurrentTypes(); 과일::겟프루트("애플"); 과일::PrintCurrentTypes(); // "Bananana"가 포함된 Fruit가 처음 사용되었을 때부터 기존 인스턴스를 반환함 // 생성됨. 과일::겟프루트("바나나"); 과일::PrintCurrentTypes(); } // 출력: // // 생성된 인스턴스 수 = 1 // 바나나 // // 생성된 인스턴스 수 = 2 // 애플 // 바나나 // // 생성된 인스턴스 수 = 2 // 애플 // 바나나 //
크리스털
계급 과일 사유의 게터 타자를 치다 : 끈 @@types = {} 의 끈 => 과일 반항하다 초기화하다(@type) 종지부를 찍다 반항하다 자아의.get_fuilt_by_type(타자를 치다 : 끈) @@types[타자를 치다] = 과일.새로운(타자를 치다) 종지부를 찍다 반항하다 자아의.show_all 놓다 "한 인스턴스 수:#{@@types.사이즈를 맞추다}" @@types.각각 하다 타자를 치다, 과실 놓다 "#{타자를 치다}" 종지부를 찍다 놓다 종지부를 찍다 반항하다 자아의.사이즈를 맞추다 @@types.사이즈를 맞추다 종지부를 찍다 종지부를 찍다 과일.get_fuilt_by_type("바나나") 과일.show_all 과일.get_fuilt_by_type("애플") 과일.show_all 과일.get_fuilt_by_type("바나나") 과일.show_all
출력:
만든 인스턴스 수: 만든 바나나 수: 만든 바나나 수: 만든 바나나 애플 수: 만든 바나나 애플 2개
헥시
클래스 과일 { private static var _instance = new Map<String, Fuilt>(); 공용 var 이름(default, null):문자열, 공용 기능 new(이름:문자열) { this.name = 이름; } 공용 정적 함수 getFulutByName(이름:문자열:과일 { if (!_instance)existance(이름) { _instance.set(이름, 새 과일(이름), } return _instance.get(이름), } public static function printAllTypes()} { trace([instance.keys() 키의 경우)]; }}}}
사용법
class Test { public static function main () { var banana = Fruit.getFruitByName("Banana"); var apple = Fruit.getFruitByName("Apple"); var banana2 = Fruit.getFruitByName("Banana"); trace(banana == banana2); // true. same banana Fruit.printAllTypes(); // ["Banana","Apple"] } }
자바
![]() | 이 예는 안전하지 않다. 토크 페이지를 참조하십시오.대신 이중 체크된 잠금#Usage_in_Java에 제공된 예를 살펴보십시오. |
자바에 예시가 있다.
수입하다 java.util.해시맵; 수입하다 java.util.지도; 수입하다 java.util.지도.엔트리; 공중의 계급 프로그램 { /** * @param args */ 공중의 정태의 공허하게 하다 본래의(끈[] 아그) { 과일.getFluentBy유형 이름(FruitType.바나나); 과일.쇼올(); 과일.getFluentBy유형 이름(FruitType.사과); 과일.쇼올(); 과일.getFluentBy유형 이름(FruitType.바나나); 과일.쇼올(); } } 열거하다 FruitType { 없는, 사과, 바나나, } 계급 과일 { 사유의 정태의 지도<FruitType, 과일> 종류들 = 새로운 해시맵<>(); /** * 민간 시공자를 사용하여 공장 방법을 사용하도록 강제함. * @param 유형 */ 사유의 과일(FruitType 타자를 치다) { } /** * Lazy Factory 메서드, 특정 과일과 연관된 과일 인스턴스 가져오기 *타입.필요에 따라 새로운 항목을 인스턴스화하십시오. * @param type 허용된 과일 유형(예: 애플) * @return 해당 유형과 관련된 과일 인스턴스. */ 공중의 정태의 과일 getFluentBy유형 이름(FruitType 타자를 치다) { 과일 과실; // 이것은 동시성 문제가 있다.여기서 read to type은 동기화되지 않는다. // 따라서 유형.put과 type.continesKey는 동시에 호출될 수 있다. // 데이터가 손상되더라도 놀라지 마십시오. 만일 (!종류들.포함키(타자를 치다)) { // 게으른 초기화 과실 = 새로운 과일(타자를 치다); 종류들.놓다(타자를 치다, 과실); } 다른 { // OK, 현재 이용 가능 과실 = 종류들.얻다(타자를 치다); } 돌아오다 과실; } /** * Lazy Factory 메서드, 특정 과일과 연관된 과일 인스턴스 가져오기 *타입.필요에 따라 새로운 항목을 인스턴스화하십시오.이중 체크된 잠금 사용 * 동시성이 높은 환경에서 사용하기 위한 패턴 * @param type 허용된 과일 유형(예: 애플) * @return 해당 유형과 관련된 과일 인스턴스. */ 공중의 정태의 과일 getFluentByTypeNameHighConcurrentVersion(FruitType 타자를 치다) { 만일 (!종류들.포함키(타자를 치다)) { 동기화된 (종류들) { // 잠금을 획득한 후 다시 확인하여 확인 // 다른 스레드에 의해 인스턴스가 생성되지 않음 만일 (!종류들.포함키(타자를 치다)) { // 게으른 초기화 종류들.놓다(타자를 치다, 새로운 과일(타자를 치다)); } } } 돌아오다 종류들.얻다(타자를 치다); } /** * 입력된 모든 과일을 표시한다. */ 공중의 정태의 공허하게 하다 쇼올() { 만일 (종류들.사이즈를 맞추다() > 0) { 시스템.밖으로.인쇄하다("한 인스턴스 수 = " + 종류들.사이즈를 맞추다()); 을 위해 (엔트리<FruitType, 과일> 입장권 : 종류들.엔트리 세트()) { 끈 과실 = 입장권.getKey().토스트링(); 과실 = 캐릭터.토퍼케이스(과실.챠랏(0)) + 과실.하위 문자열(1); 시스템.밖으로.인쇄하다(과실); } 시스템.밖으로.인쇄하다(); } } }
출력
만든 인스턴스 수 = 만든 바나나 수 = 만든 인스턴스 수 = 만든 바나나 애플 수 = 만든 인스턴스 수 = 2 바나나 애플
자바스크립트
자바스크립트의 예는 다음과 같다.
시합을 하다 과일 = (기능을 발휘하다() { 시합을 하다 종류들 = {}; 기능을 발휘하다 과일() {}; // 개체에서 자체 속성 카운트 기능을 발휘하다 수를 세다(오비지) { 돌아오다 오브젝트.열쇠들.(오비지).길이; } 시합을 하다 정전기적 = { getFruit: 기능을 발휘하다(타자를 치다) { 만일 (활자의 종류들[타자를 치다] == '정의되지 않음') { 종류들[타자를 치다] = 새로운 과일; } 돌아오다 종류들[타자를 치다]; }, printCurrentTypes: 기능을 발휘하다 () { 위로하다.통나무를 하다('작성된 인스턴스 수: ' + 수를 세다(종류들)); 을 위해 (시합을 하다 타자를 치다 에 종류들) { 위로하다.통나무를 하다(타자를 치다); } } }; 돌아오다 정전기적; })(); 과일.getFruit('애플'); 과일.printCurrentTypes(); 과일.getFruit('바나나'); 과일.printCurrentTypes(); 과일.getFruit('애플'); 과일.printCurrentTypes();
출력
만든 인스턴스 수: 1개의 애플 인스턴스 수: 2개의 애플 바나나 인스턴스 수: 2개의 애플 바나나
PHP
PHP 7.4의 게으른 초기화의 예는 다음과 같다.
<?php 머리글('Content-Type: text/plain; charset=utf-8'); 계급 과일 { 사유의 끈을 매다 $type; 사유의 정태의 배열하다 달러화 = 배열하다(); 사유의 기능을 발휘하다 ____(끈을 매다 $type) { $ this->타자를 치다 = $type; } 공중의 정태의 기능을 발휘하다 getFruit(끈을 매다 $type) { // 여기서 게으른 초기화가 수행됨 만일 (!설정하다(자아의::종류들[$type])) { 자아의::종류들[$type] = 새로운 과일($type); } 돌아오다 자아의::종류들[$type]; } 공중의 정태의 기능을 발휘하다 printCurrentTypes(): 공허하게 하다 { 메아리치다 '작성된 인스턴스 수: ' . 수를 세다(자아의::종류들) . "\n"; 앞을 내다 (array_keys(자아의::종류들) 로서 $key) { 메아리치다 "$key\n"; } 메아리치다 "\n"; } } 과일::getFruit('애플'); 과일::printCurrentTypes(); 과일::getFruit('바나나'); 과일::printCurrentTypes(); 과일::getFruit('애플'); 과일::printCurrentTypes(); /* 출력: 만든 인스턴스 수: 1 사과 만든 인스턴스 수: 2 사과 바나나 만든 인스턴스 수: 2 사과 바나나 */
파이톤
여기 파이썬의 예가 있다.
계급 과일: 반항하다 __init___(자아의, 항목: 발을 동동 구르다) -> 없음: 자아의.항목 = 항목 계급 과일들: 반항하다 __init___(자아의) -> 없음: 자아의.항목들 = {} 반항하다 get_fruit(자아의, 항목: 발을 동동 구르다) -> 과일: 만일 항목 아닌 에 자아의.항목들: 자아의.항목들[항목] = 과일(항목) 돌아오다 자아의.항목들[항목] 만일 __name__ == "__main__": 과일들 = 과일들() 인쇄하다(과일들.get_fruit("애플")) 인쇄하다(과일들.get_fruit("라임"))
루비
구글과 같은 원격 서비스에서 인증 토큰을 느릿느릿 초기화한 루비의 예가 여기에 있다.@auth_token이 캐시되는 방식도 메모화의 예다.
요구하다 '그물/그물' 계급 블로거 반항하다 auth_properties @auth_properties = (재방송하다 = 그물::HTTP.post_form(우리당, 모조품)) && get_properties_from_response(재방송하다) 종지부를 찍다 # get_built_from_response, uri 및 params는 클래스 후반부에 정의된다. 종지부를 찍다 b = 블로거.새로운 b.instance_instance_get(:@auth_message) # 영을 돌려주다. b.auth_properties # 토큰 반환 b.instance_instance_get(:@auth_message) # 토큰 반환
스칼라
스칼라는 게으른 변수 개시를 위한 지원을 내장하고 있다.[2]
스칼라> 발랄하게 하다 x = { 인쇄하다("여보세요"); 99 } 안녕 x: 인트 = 99 스칼라> 게을러진 발랄하게 하다 y = { 인쇄하다("여보세요!!"); 31 } y: 인트 = <게을러진> 스칼라> y 안녕!! res2: 인트 = 31 스칼라> y res3: 인트 = 31
스몰토크
다음은 스몰토크에서 게으른 초기화를 사용하여 변수의 값을 반환하는 일반적인 접근자 방법의 예다.
^높이 ifNil: [높이 := 2.0]
'비 레이지(non-lazy)' 대안은 객체가 생성될 때 실행되는 초기화 방법을 사용한 다음 보다 간단한 접근자 방법을 사용하여 값을 가져오는 것이다.
초기화하다 높이 := 2.0 높이 ^높이
게으른 초기화는 비객체 지향 언어에서도 사용될 수 있다는 점에 유의하십시오.
이론 전산학
이론 컴퓨터 과학 분야에서 게으른 초기화[3](게을러 배열이라고도 함)는 초기화할 필요가 없는 메모리와 함께 작동할 수 있는 데이터 구조를 설계하는 기법이다.구체적으로, 우리가 n개의 초기화되지 않은 메모리 셀(1부터 n까지의 번호)의 테이블 T에 접근할 수 있다고 가정하고, 이 어레이의 m 셀을 할당하고자 한다. 예를 들어, 우리는 모든 k가i 다른 쌍(k1, v1), ..., (km, vm)에 T[ki] := v를i 할당하고자 한다.게으른 초기화 기법은 O(m+n) 연산을 해서 먼저 모든 어레이 셀을 초기화하는 것이 아니라 O(m) 연산만으로 이것을 할 수 있게 해준다.기법은 단순히 쌍(ki, vi)을 저장하는 테이블 V를 임의의 순서로 할당하고, 키 k가i 저장되는 V[ki] 위치에 각 i에 대해 키 k가 저장되는 위치를 기록하여 T의 다른 셀은 초기화되지 않은 상태로 두는 것이다.이것은 다음과 같은 방식으로 쿼리를 처리할 수 있다: 셀 T[k]에서 k를 찾을 때 k가 {1, ..., m: 만약 그렇지 않다면 T[k]는 초기화되지 않는다.그렇지 않으면 V[T]를 확인하고 이 쌍의 첫 번째 구성 요소가 k와 동일한지 확인하십시오.그렇지 않으면 T[k]가 초기화되지 않은 것이다(그리고 우연히 {1, ..., m} 범위에 속함).그렇지 않으면 T[k]가 실제로 초기화된 셀 중 하나이며, 해당 값은 쌍의 두 번째 성분이라는 것을 알고 있다.
참고 항목
참조
- ^ "Lazy initialization - Design patterns - Haxe programming language cookbook". 2018-01-11. Retrieved 2018-11-09.
- ^ Pollak, David (2009-05-25). Beginning Scala. ISBN 9781430219897.
- ^ Moret, B. M. E.; Shapiro, H. D. (1991). Algorithms from P to NP, Volume 1: Design & Efficiency. Benjamin/Cummings Publishing Company. pp. 191–192. ISBN 0-8053-8008-6.