유형 자기성찰
Type introspection![]() |
컴퓨팅에서 유형 자기성찰은 프로그램이 런타임에 개체의 유형이나 속성을 검사할 수 있는 능력이다. 일부 프로그래밍 언어들은 이 능력을 가지고 있다.
Introspection should not be confused with reflection, which goes a step further and is the ability for a program to manipulate the values, metadata, properties, and functions of an object at runtime. 일부 프로그래밍 언어는 또한 그러한 기능(예: Java, Python, Julia, Go)을 가지고 있다.
예
루비
유형 내성은 루비의 핵심 특징이다. Ruby에서 Object 클래스(모든 클래스의 관리자)는 Object#instance_of?
그리고 Object#kind_of?
인스턴스의 클래스를 확인하는 방법. 메시지를 보낸 특정 인스턴스가 해당 클래스의 후예 인스턴스일 때 후자는 참으로 돌아온다. 예를 들어 다음 예 코드를 고려해 보십시오(Interactive Ruby Shell을 사용하여 즉시 시도 가능).
$ irb irb(main):001:0> A=클래스.새로운 => A irb(main):002:0> B=클래스.새로운 A => B irb(main):003:0> a=A.새로운 => #<0x2e44b78> irb(main):004:0> b=B.새로운 => #<0x2e431b0> irb(main):005:0> a.instance_of? A => 참 irb(main):006:0> b.instance_of? A => 거짓 irb(main):007:0> b.어떤 종류의? A => 참
위의 예에서, Class
루비에서 클래스는 다른 클래스로 사용된다. 두 개의 클래스가 만들어지고 A
그리고 B
전자는 후자의 슈퍼클래스가 되고, 그 다음 각 클래스의 한 예를 점검한다. 마지막 표현은 진실이다. A
의 최상급이다. b
.
또한 어떤 물체의 클래스를 직접 요청하여 "비교"할 수 있다(아래 코드는 위의 코드를 실행한 것으로 가정함).
irb(main):008:0> A.instance_of? 클래스 => 참 irb(main):009:0> a.계급 => A irb(main):010:0> a.계급.계급 => 클래스 irb(main):011:0> A > B => 참 irb(main):012:0> B <= A => 참
목표-C
예를 들어 Object-C에서는 일반 Object와 NSObject(Cocoa/OpenStep)가 모두 방법을 제공한다. isMemberOfClass:
메서드에 대한 인수가 지정된 클래스의 인스턴스인 경우 true를 반환한다. 방법 isKindOfClass:
인수가 지정된 클래스에서 상속되는 경우 유사하게 true를 반환한다.
예를 들어, 우리가 가지고 있다고 하자. Apple
그리고 Orange
에서 상속되는 클래스 Fruit
.
자, 이제. eat
우리가 쓸 수 있는 방법
- (공허하게 하다)식사:(id)…의 { 만일 ([…의 isKindOfClass:[과일 계급]]) { // 실제로 과일을 먹고 있으니 계속하십시오. 만일 ([…의 isMemberOfClass:[사과 계급]]) { 애플을 먹다(…의); } 다른 만일 ([…의 isMemberOfClass:[오렌지 계급]]) { 오랑쥬를 먹다(…의); } 다른 { 착오(); } } 다른 { 착오(); } }
자, 언제 eat
일반적 객체를 사용하여 호출된다). id
)) 함수는 일반 물체의 유형에 따라 올바르게 동작한다.
C++
C++는 RTTI(런타임 유형 정보) typeid 및 dynamic_cast 키워드를 통해 유형 내성을 지원한다. 그 dynamic_cast
표현식은 특정 객체가 특정 파생 클래스의 것인지 여부를 결정하는 데 사용될 수 있다. 예를 들어,
사람* p = 다이나믹_캐스트<사람 *>(오비지); 만일 (p != 무효의) { p->걷다(); }
그 typeid
운영자가 a를 검색하다. std::type_info
객체의 가장 파생된 유형을 설명하는 객체:
만일 (활자의(사람) == 활자의(*오비지)) { 연재하다_사람( 오비지 ); }
객체 파스칼
유형 자기성찰은 시각적 폼 디자인에 RTTI를 많이 사용하는 델파이 원작 출시 이후 오브젝트 파스칼의 일부였다. Object Pascal에서 모든 클래스는 기본 RTTI 기능을 구현하는 기본 TOBject 클래스에서 하강한다. 모든 클래스의 이름은 RTTI 목적을 위한 코드에서 참조될 수 있다. 클래스 이름 식별자는 클래스의 메타데이터에 대한 포인터로서 구현된다. 이는 TClass 유형의 변수로 선언되고 사용될 수 있다. 언어는 어떤 물체가 주어진 클래스에서 내려오는지 결정하기 위해 연산자, 연산자로써, 형식 확인 타이프캐스트를 제공하며, 몇 가지 TObject 방법을 포함한다. 심층 자기성찰(장 및 방법의 과민성)은 전통적으로 $M+(실용성) 상태로 선언된 개체, 일반적으로 TP존재하며, 발행된 절에 정의된 기호에 대해서만 지원된다. 델파이 2010은 이것을 거의 모든 상징으로 증가시켰다.
절차 양식1.MyButtonClick(보낸 사람: 토버젝트); 시합을 하다 a버튼: 트부턴; 센더클래스: TClass; 시작되다 센더클래스 := 보낸 사람.클래스 유형; //발신자의 클래스 포인터 반환 만일 발송인 이다 트부턴 그때 시작되다 a버튼 := 발송인 로서 트부턴; 편집박스.텍스트 := a버튼.캡션; //버튼에는 있지만 일반 개체는 없는 속성 종지부를 찍다 다른 시작되다 편집박스.텍스트 := 보낸 사람.클래스 이름; //보내기 클래스의 이름을 문자열로 반환 종지부를 찍다; 종지부를 찍다;
자바
Java에서 유형 내성의 가장 간단한 예는 다음과 같다. instanceof
[1] 교환원의 그 instanceof
운영자는 특정 객체가 특정 클래스(또는 해당 클래스의 하위 클래스 또는 해당 인터페이스를 구현하는 클래스)에 속하는지 여부를 결정한다. 예를 들어,
만일 (오비지 의 예. 사람) { 사람 p = (사람)오비지; p.걷다(); }
그 java.lang.Class
[2] 수업은 더 진보된 자기 성찰의 기본이다.
예를 들어, (특정 클래스의 멤버인지 아닌) 객체의 실제 클래스를 결정하는 것이 바람직한 경우, Object.getClass()
그리고 Class.getName()
사용할 수 있는 항목:
시스템.밖으로.인쇄하다(오비지.get클래스().getName());
PHP
PHP에서는 다음을 사용하여 자기성찰을 수행할 수 있다. instanceof
교환원의 예를 들어,
만일 ($obj 의 예. 사람) { // 하고 싶은 대로 해 }
펄
다음을 사용하여 내성할 수 있다. ref
그리고 isa
펄의 함수.
우리는 다음과 같은 클래스 및 그에 상응하는 예를 살펴볼 수 있다.
꾸러미 애니멀; 후보선수 새로운 { 나의 $class = 교대시키다; 돌아오다 축복을 빌다 {}, $class; } 꾸러미 개; 사용하다 밑의 '동물'; 꾸러미 본래의; 나의 달러화 = 애니멀->새로운(); 나의 $dog = 개->새로운();
사용:
인쇄하다 "이것은 애니멀이야.\n" 만일 참조하다 달러화 eq '동물'; 인쇄하다 "개는 동물이다.\n" 만일 $dog->이사하다('동물');
메타 객체 프로토콜
Perl에서 훨씬 더 강력한 자기성찰은 무스 오브젝트 시스템과[3] 그 시스템을 사용하여 성취될 수 있다. Class::MOP
예를 들어,[4] 지정된 개체가 역할을 수행하는지 여부를 확인할 수 있는 메타 개체 프로토콜 X:
만일 ($객체->변형시키다->does_messages("X")) { ♪ 뭔가를 해 ♪ }
이렇게 하면 개체에서 호출할 수 있는 모든 메서드의 정규화된 이름을 정의된 클래스와 함께 나열할 수 있다.
을 위해 나의 달러화 ($객체->변형시키다->get_all_message) { 인쇄하다 달러화->full_qualified_name, "\n"; }
파이톤
Python에서 가장 일반적인 자기성찰 방법은 를 사용하는 것이다. dir
물체의 속성을 상세히 기술하는 기능. 예를 들면 다음과 같다.
계급 푸: 반항하다 __init___(자아의, 발랄하게 하다): 자아의.x = 발랄하게 하다 반항하다 술집을 내다(자아의): 돌아오다 자아의.x
>>> 디르(푸(5)) ['__class__', '_delattr__', '__doc__', '_getattribute___', '_getattribute_', '_', '_delattr__', '_', ' '__back__', '_init__', '_new__', '_new__', '_new__', '_new__', '_new__', '_new___x_', '_new__x_', ' '__repr__', '_setattr__', '_str_', '__ref_', 'bar', 'x']
또한 내장 기능 type
그리고 isinstance
어떤 물체가 있는 동안 어떤 물체가 있는가를 결정하는 데 사용될 수 있다. hasattr
물체가 무엇을 하는지를 결정할 수 있다. 예를 들면 다음과 같다.
>>> a = 푸(10) >>> b = 바(11) >>> 타자를 치다(a) <형식 '후' > >>> 현시점(a, 푸) 진실의 >>> 현시점(a, 타자를 치다(a)) 진실의 >>> 현시점(a, 타자를 치다(b)) 거짓의 >>> 하삿트레(a, '바') 진실의
ActionScript(as3)
ActionScript에서 함수 flash.utils.getQualifiedClassName
임의 객체의 클래스/유형 이름을 검색하는 데 사용할 수 있다.
// as3에서 사용되는 모든 클래스는 명시적으로 가져와야 함 수입하다 섬광하다.이용하다.getQualifiedClassName; 수입하다 섬광하다.전시하다.스프라이트; // 추적은 Java의 System.out.println이나 PHP의 에코와 같다. 자취를 감추다(섬광하다.이용하다.getQualifiedClassName("나는 스트링이다")); // "끈" 자취를 감추다(섬광하다.이용하다.getQualifiedClassName(1)); // "int", 동적 주물에서 숫자가 아닌 이유를 참조하십시오. 자취를 감추다(섬광하다.이용하다.getQualifiedClassName(새로운 섬광하다.전시하다.스프라이트())); // "플래시.디스플레이"스프라이트"
또는 연산자 is
객체가 특정 유형인지 확인하는 데 사용할 수 있음:
// 추적은 Java의 System.out.println이나 PHP의 에코와 같다. 자취를 감추다("나는 스트링이다" 이다 끈); // 참 자취를 감추다(1 이다 끈); // 거짓 자취를 감추다("나는 스트링이다" 이다 숫자); // 거짓 자취를 감추다(1 이다 숫자); // 참
이 두 번째 기능은 학급 상속 부모들을 테스트하는 데도 사용될 수 있다.
수입하다 섬광하다.전시하다.DisplayObject; 수입하다 섬광하다.전시하다.스프라이트; // DisplayObject 확장 자취를 감추다(새로운 섬광하다.전시하다.스프라이트() 이다 섬광하다.전시하다.스프라이트); // 참 자취를 감추다(새로운 섬광하다.전시하다.스프라이트() 이다 섬광하다.전시하다.DisplayObject); // 참, 스프라이트가 DisplayObject를 확장하기 때문에 자취를 감추다(새로운 섬광하다.전시하다.스프라이트() 이다 끈); // 거짓
메타형 자기성찰
Perl과 마찬가지로 ActionScript는 클래스 이름을 얻는 것보다 더 멀리 나아갈 수 있지만, 를 사용하여 객체를 구성하는 모든 메타데이터, 함수 및 기타 요소들은 flash.utils.describeType
함수; 이것은 ActionScript에서 반사를 구현할 때 사용된다.
수입하다 섬광하다.이용하다.묘사하다유형; 수입하다 섬광하다.이용하다.getDefinitionByName; 수입하다 섬광하다.이용하다.getQualifiedClassName; 수입하다 섬광하다.전시하다.스프라이트; 시합을 하다 className:끈 = getQualifiedClassName(새로운 섬광하다.전시하다.스프라이트()); // "플래시.디스플레이"스프라이트" 시합을 하다 classRef:클래스 = getDefinitionByName(className); // flash.display에 대한 클래스 참조{오타가 아니에요.}}}스프라이트 // 예: 'new classRef()'와 'new flash.display'와 동일함.스프라이트() 자취를 감추다(묘사하다유형(classRef)); // 유형을 설명하는 XML 개체 반환 // trace와 동일(describeType(flash.display)스프라이트);;