맨위로가기

반영 (컴퓨터 과학)

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

반영(Reflection)은 런타임에 프로그램의 구조와 동작을 검사하고 수정할 수 있는 프로그래밍 기법이다. 초기 컴퓨터의 어셈블리 언어에서 시작되어, 고급 프로그래밍 언어의 유형 시스템에 내장되어 발전했다. 반영을 통해 코드의 동적 수정, 일반적인 소프트웨어 라이브러리 작성, 네트워크 지향 코드의 구현 등이 가능하며, 객체 지향 프로그래밍 언어에서는 클래스, 인터페이스, 필드, 메서드를 검사하고 조작하는 데 사용된다. 하지만 보안 취약점을 유발할 수 있다는 단점도 존재한다. C#, 자바, 파이썬, Objective-C, Perl, PHP, 루비 등 다양한 프로그래밍 언어에서 반영을 구현하고 있으며, 각 언어별로 고유한 방식으로 클래스 인스턴스 생성, 메서드 호출 등의 기능을 제공한다.

더 읽어볼만한 페이지

  • 프로그래밍 패러다임 - 지식 표현
    지식 표현은 컴퓨터가 인간의 지식을 이해하고 활용하도록 정보를 구조화하는 기술이며, 표현력과 추론 효율성의 균형, 불확실성 처리 등을 핵심 과제로 다양한 기법과 의미 웹 기술을 활용한다.
  • 프로그래밍 패러다임 - 의도적 프로그래밍
    의도적 프로그래밍은 프로그래머의 의도를 명확히 포착하고 활용하여 소프트웨어 개발 생산성을 향상시키기 위한 프로그래밍 패러다임으로, 트리 기반 저장소를 사용해 코드 의미 구조를 보존하고, WYSIWYG 환경에서 도메인 전문가와 협업하며, 코드 상세 수준 조절 및 자동 문서화를 통해 가독성과 유지보수성을 높이는 데 중점을 둔다.
반영 (컴퓨터 과학)

2. 역사적 배경

초창기 컴퓨터는 고유의 어셈블리 언어로 프로그래밍되었는데, 이러한 초기 아키텍처는 명령어를 데이터로 정의하고 자기 수정 코드를 사용하여 프로그래밍할 수 있었기 때문에 본질적으로 반사적이었다. 프로그래밍의 대부분이 알골, 코볼, 포트란, 파스칼, C와 같은 고급 컴파일 언어로 이동하면서 이러한 반사적 능력은 타입 시스템에 반사 기능을 내장한 새로운 프로그래밍 언어가 등장할 때까지 대부분 사라졌다.

브라이언 캔트웰 스미스는 1982년 박사 학위 논문에서 절차적 프로그래밍 언어에서의 계산적 반영 개념과 3-Lisp의 구성 요소로서 메타-순환 인터프리터의 개념을 소개했다.[2][3]

3. 기능


  • 런타임에 일급 객체로서 소스 코드의 생성자(코드 블록, 메소드, 프로토콜 등)를 인식하고 수정할 수 있다.[1]
  • 참조 및 호출되는 클래스 또는 함수와 일치하는 문자열을 클래스 또는 함수의 기호 이름으로 변환할 수 있다.[1]
  • 런타임에 소스 코드 구문으로 구성된 문자열을 평가할 수 있다.[1]
  • 프로그래밍 구성에 새로운 의미 또는 의도를 부여하여, 프로그램 언어의 바이트코드에 대한 새로운 번역기를 생성할 수 있다.[1]

4. 이용

반영은 런타임에 프로그램의 실행을 수정하고 관찰하는 데 사용될 수 있다. 반영 지향적인 프로그램 구성 요소는 코드 실행을 감시하고, 자신의 목표에 맞게 스스로를 수정할 수 있다. 이는 동적으로 상황에 따라 프로그램이 사용될 수 있도록 한다. (예: 비슷한 동작을 수행하는 서로 다른 클래스를 교체하여 사용) 하드 코딩을 방지하고, 보다 일반적인(Generic) 코드 수행 기능을 사용할 수 있도록 한다.

반영은 프로그래머가 일반적인 소프트웨어 라이브러리를 만드는 데 도움을 준다. 예를 들어, 데이터를 표시하고, 다양한 형식의 데이터를 처리하고, 통신을 위해 데이터의 직렬화 및 역직렬화를 수행하거나, 컨테이너 또는 통신 버스트를 위한 데이터의 번들링 및 언번들링을 수행하는 라이브러리를 만들 수 있다.

반영은 언어를 네트워크 지향 코드에 더 적합하게 만든다. 예를 들어, 자바와 같은 언어가 직렬화, 번들링 및 다양한 데이터 형식에 대한 라이브러리를 활성화하여 네트워크에서 잘 작동하도록 돕는다. C와 같이 반영이 없는 언어는 추상 구문 표기법과 같은 작업을 위해 보조 컴파일러를 사용하여 직렬화 및 번들링 코드를 생성해야 한다.

객체 지향 프로그래밍 언어, 예를 들어 자바에서 반영을 사용하면 컴파일 타임에 인터페이스, 필드, 메서드의 이름을 알지 못해도 런타임에 클래스, 인터페이스, 필드 및 메서드를 ''검사''할 수 있다. 또한 새로운 객체의 ''인스턴스화''와 메서드의 ''호출''도 허용한다.

반영은 모의 객체의 런타임 생성/인스턴스화와 같은 소프트웨어 테스트의 일부로 자주 사용된다.

반영은 또한 메타 프로그래밍의 핵심 전략이다.

C# 및 자바와 같은 일부 객체 지향 프로그래밍 언어에서 반영을 사용하여 멤버 접근성 규칙을 우회할 수 있다. C# 속성의 경우, 일반적으로 보이지 않는 비공개 속성의 지원 필드에 직접 작성하여 이를 수행할 수 있다. 또한 클래스 및 유형의 비공개 메서드를 찾아 수동으로 호출할 수도 있다. 이는 .NET 어셈블리 및 자바 아카이브와 같은 외부 라이브러리뿐만 아니라 프로젝트 내부 파일에도 적용된다.

5. 구현

반영은 다양한 방식으로 구현될 수 있다.


  • 소스 코드 구성 요소(코드 블록, 클래스, 메서드, 프로토콜 등)를 일급 객체로 런타임에 검색하고 수정하는 기능.
  • 클래스 또는 함수의 기호 이름과 일치하는 문자열을 해당 클래스 또는 함수에 대한 참조 또는 호출로 변환.
  • 런타임에 소스 코드 문인 것처럼 문자열을 평가.
  • 언어의 바이트코드에 대한 새로운 인터프리터를 생성하여 프로그래밍 구성 요소에 대한 새로운 의미나 목적을 부여.


이러한 기능은 여러 방식으로 구현될 수 있다. MOO에서는 반성이 자연스럽게 프로그래밍 방식의 일부로 사용된다. 동사(메서드)가 호출될 때 'verb'(호출되는 동사의 이름) 및 'this'(동사가 호출되는 객체)와 같은 변수들이 채워져 호출의 문맥을 제공한다. 보안은 호출자 스택에 프로그래밍 방식으로 접근하여 관리된다. 'callers'()는 현재 동사가 호출되기까지의 메서드 목록을 나타내므로, 'callers'()[0](원래 사용자가 호출한 명령)에 대한 테스트를 수행하여 동사가 무단 사용으로부터 보호받을 수 있도록 한다.

컴파일된 언어는 런타임 시스템에 의존하여 소스 코드에 대한 정보를 제공한다. 예를 들어, 컴파일된 Objective-C 실행 파일은 실행 파일 블록에 있는 모든 메서드의 이름을 기록하고, 이러한 메서드를 프로그램에 컴파일된 기본 메서드(또는 이러한 메서드에 대한 선택자)에 매핑하는 테이블을 제공한다. Common Lisp와 같이 런타임에 함수 생성을 지원하는 컴파일된 언어의 경우, 런타임 환경에는 컴파일러 또는 인터프리터가 포함되어야 한다.

반성은 자동화된 소스 코드 변경을 정의하기 위해 프로그램 변환 시스템을 사용하여 내장된 반성이 없는 언어에도 구현될 수 있다.

반영은 스몰토크, 자바, .NET Framework와 같은 가상 머신이나 인터프리터 위에서 실행되는 것을 전제로 하는 언어에서 지원되는 경우가 많으며, C 언어와 같은 기계어로 출력되는 것을 전제로 하는 언어에서는 지원되는 경우가 적다.

일반적으로 프로그램의 소스 코드컴파일되면 프로그램의 구조 등의 정보는 저레벨 코드(어셈블리 언어 등)로 변환되는 과정에서 사라진다. 리플렉션을 지원하는 경우, 그러한 정보는 생성되는 코드 안에 메타데이터로서 저장된다.

6. 보안 고려 사항

반영은 사용자가 애플리케이션을 통해 예상치 못한 제어 흐름 경로를 생성하도록 허용하여 잠재적으로 보안 조치를 우회할 수 있게 한다. 이는 공격자에 의해 악용될 수 있다.[4] 안전하지 않은 반영으로 인해 발생한 Java의 역사적인 취약점은 잠재적으로 신뢰할 수 없는 원격 시스템에서 검색된 코드가 Java 샌드박스 보안 메커니즘에서 벗어나도록 했다. 2013년 120개의 Java 취약점에 대한 대규모 연구 결과에 따르면 안전하지 않은 반영이 Java에서 가장 흔한 취약점이지만 가장 많이 악용되는 취약점은 아니다.[5]

7. 예제

다음은 여러 프로그래밍 언어에서 리플렉션을 사용하는 예시를 보여준다. 각 예시는 `Foo` 클래스의 인스턴스를 생성하고 `hello` 메서드를 호출하는 일반적인 방법과 리플렉션을 사용하는 방법을 비교한다.

다양한 프로그래밍 언어에서의 리플렉션 예제
언어일반적인 호출리플렉션 기반 호출
C#
Objective-C
파이썬
Java
JavaScript
Perl
PHP
Ruby
R
Xojo
Delphi
eC
Go
Common Lisp
Julia



각 언어별 리플렉션 예제에 대한 자세한 내용은 하위 섹션을 참고할 수 있다.

7. 1. C#

csharp

// 리플렉션 없이

var foo = new Foo();

foo.PrintHello();

// 리플렉션 사용

Object foo = Activator.CreateInstance("완전한.경로.및.Foo");

MethodInfo method = foo.GetType().GetMethod("PrintHello");

method.Invoke(foo, null);

```

위 코드는 C#에서 리플렉션을 사용하여 `Foo` 클래스의 `PrintHello` 메서드를 호출하는 방법을 보여준다. 리플렉션을 사용하면 런타임에 객체의 형식 정보를 얻고, 메서드를 호출하거나 속성 값을 가져오는 등의 작업을 수행할 수 있다.

아래는 C# 리플렉션을 사용하여 특정 어셈블리에서 사용자 지정 특성(`RecentlyModifiedAttribute`)이 적용된 메서드를 찾아 정보를 출력하는 코드이다.

```csharp

using System;

using System.Reflection;

using Recent;

namespace Reflect

{

class Program

{

private Assembly a;

Program(String assemblyName)

{

a = Assembly.Load(new AssemblyName(assemblyName));

// 지정된 어셈블리에 SupportsRecentlyModifiedAttribute 속성이 적용되었는지 확인

Attribute c = Attribute.GetCustomAttribute(a, typeof(SupportsRecentlyModifiedAttribute));

if (c == null)

{

throw new Exception("어셈블리 " + assemblyName + "는 필요한 속성을 지원하지 않습니다.");

}

Console.WriteLine("로드 완료: " + a.FullName);

}

public void FindNewMethodsWithNoArgs()

{

// 어셈블리에 정의된 모든 형식을 가져옴

Type[] t = a.GetTypes();

foreach (Type type in t)

{

// 클래스가 아니면 건너뜀

if (!type.IsClass)

continue;

Console.WriteLine("클래스 이름: " + type.FullName);

MethodInfo[] methods = type.GetMethods();

foreach (MethodInfo method in methods)

{

object[] ab = method.GetCustomAttributes(typeof(RecentlyModifiedAttribute), true);

// RecentlyModifiedAttribute 속성이 없으면 오래된 메서드

if (ab.Length != 0)

{

Console.Write("\t업데이트된 메서드: " + method.Name);

if (method.GetParameters().Length > 0)

break;

// RecentlyModifiedAttribute 속성의 주석을 가져옴

Console.WriteLine("\t" + (ab[0] as RecentlyModifiedAttribute).comment);

Console.WriteLine("\t\t반환 형식: " + method.ReturnType.Name);

}

}

}

}

static void Main(string[] args)

{

try

{

Program reflector = new Program("UseAttributes");

reflector.FindNewMethodsWithNoArgs();

}

catch (Exception e)

{

Console.Error.WriteLine(e.Message);

}

}

}

}

```

`RecentlyModifiedAttribute` 및 `SupportsRecentlyModifiedAttribute`는 사용자 지정 특성이다.

```csharp

using System;

namespace Recent

{

// 메서드에만 적용 가능, 다른 특성과 함께 사용 불가

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]

public class RecentlyModifiedAttribute : Attribute

{

private String Comment = "이 메서드는 최근에 변경되었습니다.";

public RecentlyModifiedAttribute() { } // 빈 생성자

// 선택적 인수 "comment" 정의

public String comment

{

get { return Comment; }

set { Comment = comment; }

}

}

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]

public class SupportsRecentlyModifiedAttribute : Attribute

{

// 인수 없이 어셈블리에 적용

public SupportsRecentlyModifiedAttribute() { } // 빈 생성자

}

}

```

`RecentlyModifiedAttribute`는 메서드가 최근에 변경되었음을 나타내고, `SupportsRecentlyModifiedAttribute`는 어셈블리가 `RecentlyModifiedAttribute`를 지원함을 나타낸다.

다음은 `RecentlyModifiedAttribute` 및 `SupportsRecentlyModifiedAttribute`를 사용하는 예제 클래스 `UseAttributes`이다.

```csharp

using System;

using Recent;

// 어셈블리가 "RecentlyModified" 속성을 지원함을 나타냄

[assembly: SupportsRecentlyModified]

namespace Reflect

{

class UseAttributes

{

private Object info;

public UseAttributes()

{

info = (object) "Hello World";

}

public void OldMethodWithNoArgs()

{

Console.WriteLine("이것은 인수를 받지 않는 오래된 메서드입니다.");

}

// 메서드가 최근에 변경되었음을 나타내기 위해 "RecentlyModified" 속성을 적용

[RecentlyModified]

public void NewMethodWithNoArgs()

{

Console.WriteLine("이것은 인수를 받지 않는 새로운 메서드입니다.");

}

public void OldMethodWithOneArg(object something)

{

info = something;

Console.WriteLine("이것은 인수를 1개 받는 오래된 메서드입니다.");

}

[RecentlyModified]

public void NewMethodWithOneArg(object something)

{

info = something;

Console.WriteLine("이것은 인수를 1개 받는 새로운 메서드입니다.");

}

}

}

```

`NewMethodWithNoArgs`와 `NewMethodWithOneArg` 메서드는 `RecentlyModifiedAttribute`로 표시되어 최근에 변경되었음을 나타낸다.

7. 2. Objective-C

objectivec

// Foo 클래스

@interface Foo : NSObject

  • (void)hello;

@end

// 리플렉션 없이 Foo 인스턴스에 "hello" 전송

Foo *obj =

[obj hello];

// 리플렉션을 사용하여 Foo 인스턴스에 "hello" 전송

id obj =

[obj performSelector: @selector(hello)];

```

```objectivec

// 리플렉션 없음

```

```objectivec

// 리플렉션

id aClass = objc_getClass("Foo");

SEL aSelector = NSSelectorFromString(@"hello");

objc_msgSend(

```

Objective-C에서 리플렉션(reflection)을 사용하여 클래스의 인스턴스를 생성하고 메서드를 호출하는 예제이다.

7. 3. Python

다음은 파이썬에서 리플렉션을 사용하여 클래스의 인스턴스를 생성하고 메서드를 호출하는 예제이다.

```python

# 리플렉션 없이

obj = Foo()

obj.hello()

# 리플렉션을 사용

obj = globals()["Foo"]()

getattr(obj, "hello")()

# eval을 사용

eval("Foo().hello()")

```

```python

# 리플렉션 없음

obj = Foo()

obj.hello()

# 리플렉션

class_name = "Foo"

method = "hello"

obj = globals()[class_name]()

getattr(obj, method)()

# eval

eval("Foo().hello()")

7. 4. Java

java

import java.lang.reflect.Method;

// 리플렉션 없이

Foo foo = new Foo();

foo.hello();

// 리플렉션으로

try {

Object foo = Foo.class.getDeclaredConstructor().newInstance();

Method m = foo.getClass().getDeclaredMethod("hello", new Class[0]);

m.invoke(foo);

} catch (ReflectiveOperationException ignored) {}

```

다음은 `java.lang.reflect` 패키지를 사용한 Java 6 이후의 예시이다.

```java

// 리플렉션 없음

Foo foo = new Foo();

foo.hello();

```

```java

// 리플렉션

Class cl = Class.forName("Foo");

Method method = cl.getMethod("hello");

method.invoke(cl.newInstance());

```

두 코드 모두 `Foo` 클래스의 인스턴스를 생성하고, 해당 인스턴스의 `hello()` 메서드를 호출한다. 전자의 예에서는 클래스 이름이나 메서드 이름이 하드 코딩되어 있어 실행 시 다른 클래스로 변경하는 것이 불가능하다. 리플렉션을 사용한 후자의 예에서는 실행 시에 이러한 내용들을 쉽게 변경할 수 있다. 하지만 그와 동시에, 후자는 읽기 어려우며, 컴파일 시 검사의 이점도 얻을 수 없다. 즉, `Foo` 클래스가 존재하지 않는다면 전자의 코드에서는 컴파일 시 오류가 발생하지만, 후자의 코드에서는 실행하기 전까지 오류가 발생하지 않는다.[1]

7. 5. JavaScript

javascript

// 리플렉션 없이

const foo = new Foo()

foo.hello()

// 리플렉션 사용

const foo = Reflect.construct(Foo)

const hello = Reflect.get(foo, 'hello')

Reflect.apply(hello, foo, [])

// eval 사용

eval('new Foo().hello()')

```

```javascript

// 리플렉션 (다른 방법)

var foo = this['Foo'];

var methodName = 'hello';

(new foo())[methodName]();

7. 6. Perl

perl

# 리플렉션 없이

my $foo = Foo->new;

$foo->hello;

# 또는

Foo->new->hello;

# 리플렉션 사용

my $class = "Foo";

my $constructor = "new";

my $method = "hello";

my $f = $class->$constructor;

$f->$method;

# 또는

$class->$constructor->$method;

# eval 사용

eval "new Foo->hello;";

```

다음은 위와 동일한 예제를 Perl로 작성한 코드이다.

```perl

# 리플렉션 없음

Foo->new->hello();

```

```perl

# 리플렉션

my $class = "Foo";

my $method = $class->can("hello");

$class->new->$method();

7. 7. PHP

다음은 PHP의 예시이다.[6]

```php

// 리플렉션 없이

$foo = new Foo();

$foo->hello();

// 리플렉션을 사용, Reflections API 사용

$reflector = new ReflectionClass("Foo");

$foo = $reflector->newInstance();

$hello = $reflector->getMethod("hello");

$hello->invoke($foo);

```

다음은 동일한 예시를 PHP로 작성한 것이다.

```php

// 리플렉션 없음

$foo = new Foo();

$foo->hello();

// 리플렉션

$reflector = new ReflectionClass('Foo');

$foo = $reflector->newInstance();

$hello = $reflector->getMethod('hello');

$hello->invoke($foo);

// 콜백 사용

$foo = new Foo();

call_user_func(array($foo, 'hello'));

// 가변 변수 구문 사용

$className = 'Foo';

$foo = new $className();

$method = 'hello';

$foo->$method();

7. 8. Ruby

루비에서 클래스 인스턴스를 생성하고 메서드를 호출하는 방법은 다음과 같다.
리플렉션을 사용하지 않는 경우```ruby

obj = Foo.new

obj.hello

```
리플렉션을 사용하는 경우```ruby

obj = Object.const_get("Foo").new

obj.send :hello

```
eval을 사용하는 경우```ruby

eval "Foo.new.hello"

```

위 코드는 모두 동일한 작업을 수행한다. `Foo` 클래스의 인스턴스를 생성하고 `hello` 메서드를 호출한다. 리플렉션을 사용하면 클래스 이름이나 메서드 이름을 문자열로 지정할 수 있어 코드가 더 동적이다.

7. 9. R

r

# 반사를 사용하지 않고, foo()가 "hello" 메서드를 가진 S3 형식의 객체를 반환한다고 가정합니다.

obj <- foo()

hello(obj)

# 반사를 사용합니다.

class_name <- "foo"

generic_having_foo_method <- "hello"

obj <- do.call(class_name, list())

do.call(generic_having_foo_method, alist(obj))

```

이 코드는 R에서 리플렉션을 사용하는 방법을 보여주는 예제이다.

  • 반사 미사용: `foo()` 함수를 호출하여 `obj` 객체를 생성하고, `hello()` 메서드를 직접 호출한다.
  • 반사 사용: `do.call()` 함수를 사용하여 `class_name` 변수에 저장된 이름의 클래스(`foo`)의 인스턴스를 생성하고, `generic_having_foo_method` 변수에 저장된 이름의 메서드(`hello`)를 호출한다.

7. 10. Xojo

vbnet

' Reflection 없이

Dim fooInstance As New Foo

fooInstance.PrintHello

' Reflection 사용

Dim classInfo As Introspection.Typeinfo = GetTypeInfo(Foo)

Dim constructors() As Introspection.ConstructorInfo = classInfo.GetConstructors

Dim fooInstance As Foo = constructors(0).Invoke

Dim methods() As Introspection.MethodInfo = classInfo.GetMethods

For Each m As Introspection.MethodInfo In methods

If m.Name = "PrintHello" Then

m.Invoke(fooInstance)

End If

Next

```

이 코드는 Xojo에서 리플렉션을 사용하여 클래스의 인스턴스를 생성하고 메서드를 호출하는 방법을 보여준다.

  • Reflection 없이: `Foo` 클래스의 새 인스턴스 `fooInstance`를 만들고, `PrintHello` 메서드를 직접 호출한다.
  • Reflection 사용: `GetTypeInfo(Foo)`를 통해 `Foo` 클래스의 정보를 가져온다. `GetConstructors`로 생성자 정보를 얻고, `constructors(0).Invoke`로 첫 번째 생성자를 호출하여 인스턴스를 생성한다. `GetMethods`로 메서드 목록을 가져온 후, `PrintHello` 메서드를 찾아 `m.Invoke(fooInstance)`로 호출한다.

7. 11. Delphi, Object Pascal

delphi

uses RTTI, Unit1;

// 리플렉션 없이

procedure WithoutReflection;

var

Foo: TFoo;

begin

Foo := TFoo.Create;

try

Foo.Hello;

finally

Foo.Free;

end;

end;

// 리플렉션 사용

procedure WithReflection;

var

RttiContext: TRttiContext;

RttiType: TRttiInstanceType;

Foo: TObject;

begin

RttiType := RttiContext.FindType('Unit1.TFoo') as TRttiInstanceType;

Foo := RttiType.GetMethod('Create').Invoke(RttiType.MetaclassType, []).AsObject;

try

RttiType.GetMethod('Hello').Invoke(Foo, []);

finally

Foo.Free;

end;

end;

```

델파이는 언매니지드(unmanaged)이면서 네이티브 컴파일되는 언어이기 때문에 주목할 만하다. 리플렉션을 지원하는 언어 대부분은 동적 프로그래밍 언어 또는 스크립트 언어(Perl), 파이썬(Python), PHP와 같거나, 자바(Java)나 C#처럼 런타임을 필요로 하는 언어이다.

7. 12. eC

eC

// 리플렉션 없이

Foo foo { };

foo.hello();

// 리플렉션 사용

Class fooClass = eSystem_FindClass(__thisModule, "Foo");

Instance foo = eInstance_New(fooClass);

Method m = eClass_FindMethod(fooClass, "hello", fooClass.module);

((void (*)())(void *)m.function)(foo);

7. 13. Go

go

import "reflect"

// 리플렉션 없이

f := Foo{}

f.Hello()

// 리플렉션으로

fT := reflect.TypeOf(Foo{})

fV := reflect.New(fT)

m := fV.MethodByName("Hello")

if m.IsValid() {

m.Call(nil)

}

```

다음은 Go를 사용하여 클래스의 인스턴스를 생성하고 해당 메서드를 호출하는 예시이다.

주어진 코드는 `Foo` 클래스의 인스턴스 `foo`를 생성하고, `Hello` 메서드를 호출한다. 일반적인 호출 방법과 리플렉션을 사용한 호출 방법을 모두 보여준다.

7. 14. Common Lisp

lisp

(defclass foo () ())

(defmethod print-hello ((f foo)) (format T "Hello from ~S~%" f))

;; 반사 없이 일반적인 방법

(let ((foo (make-instance 'foo)))

(print-hello foo))

;; "foo"라는 이름의 클래스와 "foo"를 전문으로 하는 "print-hello"라는 이름의 메서드를 찾기 위한 반사 사용

(let* ((foo-class (find-class (read-from-string "foo")))

(print-hello-method (find-method (symbol-function (read-from-string "print-hello"))

nil (list foo-class))))

(funcall (sb-mop:method-generic-function print-hello-method)

(make-instance foo-class)))

7. 15. Julia

julia

struct Point

x::Int

y

end

# 리플렉션을 이용한 검사

fieldnames(Point)

fieldtypes(Point)

p = Point(3,4)

# 리플렉션을 이용한 접근

getfield(p, :x)

참조

[1] 간행물 A Tutorial on Behavioral Reflection and its Implementation by Jacques Malenfant et al. http://www2.parc.com[...] unknown 2019-06-23
[2] 논문 Procedural Reflection in Programming Languages http://hdl.handle.ne[...] Department of Electrical Engineering and Computer Science, Massachusetts Institute of Technology 1982
[3] 간행물 Reflection and semantics in a procedural language http://publications.[...] Massachusetts Institute of Technology 1982-01
[4] 보고서 Static Analysis of Implicit Control Flow: Resolving Java Reflection and Android Intents https://homes.cs.was[...] University of Washington 2015-08
[5] 잡지 Twenty years of Escaping the Java Sandbox http://phrack.org/is[...] 2021-10-05
[6] 웹사이트 PHP: ReflectionClass - Manual https://www.php.net/[...]



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com