Java가 함수 정의가 클래스 외부에 존재하지 않는 이유는 무엇입니까? 있고 클래스

C ++과 달리 Java에서는 클래스에 함수 선언 만 있고 클래스 외부에 정의를 가질 수 없습니다. 왜 그래야만하지?

Java의 단일 파일에는 클래스가 하나만 있어야하며 다른 클래스는 없어야한다는 점을 강조해야합니까?



답변

C ++과 Java의 차이점은 언어가 가장 작은 연결 단위를 고려하는 것입니다.

C는 어셈블리와 공존하도록 설계되었으므로 해당 장치는 주소에 의해 호출되는 서브 루틴입니다. (이것은 FORTRAN과 같은 기본 객체 파일로 컴파일되는 다른 언어의 경우에 해당됩니다.) 즉, 함수 foo()를 포함하는 객체 파일에는 다음과 같은 주소로만 _foo해석 되는 심볼 이 있습니다.0xdeadbeef연결하는 동안. 그게 다야. 함수가 인수를 취하는 경우, 주소를 호출하기 전에 함수가 기대하는 모든 것이 순서대로되어 있는지 확인하는 것은 호출자에게 달려 있습니다. 일반적으로 이것은 스택에 물건을 쌓아서 수행되며 컴파일러는 거친 작업을 처리하고 프로토 타입이 일치하는지 확인합니다. 오브젝트 파일 간에는이를 확인하지 않습니다. 통화 연결을 끊으면 통화가 계획대로 진행되지 않고 경고 메시지가 표시되지 않습니다. 위험에도 불구하고 여러 언어 (조립 포함)로 컴파일 된 객체 파일을 많은 번거 로움없이 작동하는 프로그램에 연결할 수 있습니다.

C ++는 모든 추가 기능에도 불구하고 동일한 방식으로 작동합니다. 컴파일러는 네임 스페이스, 클래스 및 메소드 / 멤버 등을 표시합니다. 클래스의 내용을 고유 한 방식으로 엉망인 단일 이름으로 병합하여이 규칙에 예를 들어, 객체 파일에 넣을 때 와 같은 방법과 런타임 과 같은 주소 Foo::bar(int baz)가 엉망이 _ZN4Foo4barEi될 수 있습니다 0xBADCAFE. 이것은 전적으로 컴파일러에 의존하기 때문에 다른 mangling 구성표를 가진 두 객체를 연결하려고하면 운이 나빠질 것입니다. 추악한 것처럼 이것은 extern "C"블록을 사용하여 맹 글링을 비활성화하여 다른 언어에서 C ++ 코드에 쉽게 액세스 할 수 있도록합니다. C ++은 C에서 자유 부동 함수 (free-floating functions)라는 개념을 물려 받았습니다. 주로 기본 객체 형식이 허용하기 때문입니다.

Java는 자체 객체 파일 형식 인 파일로 격리 된 세상에 사는 다른 야수입니다 .class. 클래스 파일에는 해당 환경에 대한 풍부한 정보가 포함되어 있어 기본 링크 메커니즘이 상상조차 할 수 없었던 런타임시 환경에서 클래스로 작업을 수행 할 수 있습니다. 그 정보는 어딘가에서 시작해야하고 그 시작점은class. 사용 가능한 정보를 통해 컴파일 된 코드는 C, C ++ 또는 기타 언어에서와 같이 소스 코드에 설명이 포함 된 별도의 파일 없이도 자체 설명 할 수 있습니다. 이는 런타임에서도 네이티브 링키지 부족을 사용하여 모든 유형의 안전 혜택 언어를 제공하며, 리플렉션을 사용하여 파일에서 임의 클래스를 피싱하고 일치하지 않는 경우 보장 된 실패로 사용할 수있게 해줍니다 .

아직 알지 못했다면이 모든 안전 기능에는 트레이드 오프가 있습니다. Java 프로그램에 연결하는 모든 것은 Java 여야합니다. ( “링크”라는 말은 한 클래스 파일의 무언가가 다른 클래스의 무언가를 가리킬 때를 의미합니다.) JNI를 사용하여 네이티브 코드에 네이티브 코드를 링크 할 수 있지만, 네이티브 측면을 어기면 암묵적인 계약이 있습니다. , 두 조각을 모두 소유하고 있습니다.

Java는 Ada가 이전 10 년에했던 것처럼 처음 도입되었을 때 사용 가능한 하드웨어에서 특히 빠르지 않았습니다. Jim Gosling만이 자신의 동기가 Java의 가장 작은 연결 단위를 만드는 데 어떤 도움을 주 었는지 말할 수는 있지만 무료 플로터를 추가하는 것이 런타임에 추가 될 수있는 추가 복잡성은 거래 킬러라고 생각할 것입니다.


답변

나는 위키 백과에 따르면, 자바는 단순하고 객체 지향적으로 설계되었다고 생각합니다. 함수는 정의 된 클래스에서 작동하도록되어 있습니다. 이러한 사고 방식으로 클래스 외부에 함수를 갖는 것은 의미가 없습니다. Java가 순수 OOP에 맞지 않기 때문에 Java가 허용하지 않는다는 결론으로 ​​도약하려고합니다.

저를위한 빠른 Google 검색은 Java 언어 디자인 동기 부여를 많이 얻지 못했습니다.


답변

진짜 질문은 C ++ 방식으로 일을 계속하는 장점은 무엇이며 헤더 파일의 원래 목적은 무엇입니까? 짧은 대답은 헤더 파일 스타일이 많은 클래스가 잠재적으로 동일한 유형을 참조 할 수있는 대규모 프로젝트에서 더 빠른 컴파일 시간을 허용한다는 것입니다. 컴파일러의 특성으로 인해 JAVA 및 .NET에서는 필요하지 않습니다.

여기 에이 답변을보십시오 : 헤더 파일이 실제로 좋습니까?


답변

Java 파일은 클래스를 나타냅니다. 수업 이외의 절차가 있다면, 그 범위는 무엇입니까? 글로벌일까요? 아니면 Java 파일이 나타내는 클래스에 속합니까?

아마도 다른 클래스보다 다른 클래스와 함께 사용되기 때문에 다른 파일 대신 Java 파일에 넣을 수 있습니다. 클래스 외부의 프로 시저가 실제로 해당 클래스와 연관되어 있다면 클래스가 속한 클래스 내부로 강제로 들어 가지 않겠습니까? Java는 이것을 클래스 내부의 정적 메소드로 처리합니다.

외부 클래스 프로 시저가 허용 된 경우 파일이 선언 된 클래스에 대한 특별한 액세스 권한이 없으므로 데이터를 변경하지 않는 유틸리티 함수로 제한합니다.

이 Java 제한 사항의 유일한 단점은 클래스와 연관되지 않은 글로벌 프로 시저가있는 경우이를 보유 할 MyGlobals 클래스를 작성하고 해당 프로 시저를 사용하는 다른 모든 파일에서 해당 클래스를 가져 오는 것입니다. .

실제로 Java 가져 오기 메커니즘이 작동하려면이 제한 사항이 필요합니다. 모든 API를 사용할 수 있으므로 Java 컴파일러는 컴파일 대상과 컴파일 대상을 정확히 알아야하므로 파일 맨 위에 명시 적 import 문이 있어야합니다. 인공 클래스로 그룹에 전역을하지 않고, 당신은 어떻게 자바 컴파일하는 컴파일러 말할 것 당신의 전역을하지 일체의 클래스 패스에 전역을? doStuff ()가 있고 다른 사람이 doStuff ()가있는 네임 스페이스 충돌은 어떻습니까? 작동하지 않습니다. MyClass.doStuff () 및 YourClass.doStuff ()를 지정하면 이러한 문제가 해결됩니다. 프로 시저가 외부가 아닌 MyClass 내부로 들어가도록 강요하면이 제한이 명확 해지고 코드에 대한 추가 제한이 적용되지 않습니다.

Java에는 많은 문제가 있습니다. 직렬화에는 사마귀가 너무 많아서 사용하기가 너무 어렵습니다 (SerialVersionUID 생각). 또한 싱글 톤 및 기타 일반적인 디자인 패턴을 파괴하는 데 사용할 수 있습니다. Object의 clone () 메소드는 deepClone () 및 shallowClone ()으로 분할되고 형식이 안전해야합니다. 모든 API 클래스는 기본적으로 (Scala에있는 방식으로) 변경 불가능할 수 있습니다. 그러나 모든 절차가 클래스에 속해야한다는 제한은 좋은 것입니다. 이 프로그램은 주로 복잡한 제한없이 언어와 코드를 단순화하고 명확하게합니다.


답변

나는 대답 한 대부분의 사람들과 유권자들이 그 질문을 오해했다고 생각합니다. C ++을 모른다는 것을 반영합니다.

“정의”및 “선언”은 C ++에서 매우 특정한 의미를 가진 단어입니다.

OP가 Java 작동 방식을 변경한다는 의미는 아닙니다. 이것은 순전히 구문에 관한 질문입니다. 나는 그것이 유효한 질문이라고 생각합니다.

C ++에는 멤버 함수 를 정의 하는 두 가지 방법이 있습니다.

첫 번째 방법은 Java 방식입니다. 모든 코드를 중괄호 안에 넣으십시오.

class Box {
public:
    // definition of member function
    void change(int newInt) {
        this._m = newInt;
    }
private:
    int _m
}

두 번째 방법 :

class Box {
public:
    // declaration of member function
    void change(int newInt);
private:
    int _m
}

// definition of member function
// this can be in the same file as the declaration
void Box::change(int newInt) {
    this._m = newInt;
}

두 프로그램은 동일합니다. 이 함수 change는 여전히 멤버 함수입니다. 클래스 외부에는 존재하지 않습니다. 또한 클래스 정의에는 Java에서와 같이 모든 멤버 함수 및 변수의 이름과 유형이 포함되어야합니다.

Jonathan Henson은 이것이 C ++에서 헤더가 작동하는 방식의 결과라고 생각합니다. 헤더 파일에 선언을 구현하고 별도의 .cpp 파일에 구현을 적용하여 프로그램이 ODR (One Definition Rule)을 위반하지 않도록 할 수 있습니다. 그러나 그것은 그 밖에 장점이 있습니다. 큰 클래스의 인터페이스를 한눈에 볼 수 있습니다.

Java에서는 추상 클래스 또는 인터페이스를 사용하여이 효과를 근사 할 수 있지만 구현 클래스와 동일한 이름을 가질 수 없으므로 다소 어색합니다.


답변

클래스 로딩 메커니즘의 인공물이라고 생각합니다. 각 클래스 파일은로드 가능한 객체의 컨테이너입니다. 클래스 파일의 “외부”는 없습니다.


답변

Java와 매우 유사한 C #은 부분 메소드가 독점적으로 전용 인 것을 제외하고는 부분 메소드를 사용하여 이러한 기능을 제공합니다.

부분 방법 : http://msdn.microsoft.com/en-us/library/6b0scde8.aspx

부분 클래스 및 메소드 : http://msdn.microsoft.com/en-us/library/wa80x488.aspx

Java가 똑같이 할 수없는 이유는 보이지 않지만 아마도이 기능을 언어에 추가하기 위해 사용자 기반에서 인식해야 할 필요성이 있는지 여부 일 수 있습니다.

C #을위한 대부분의 코드 생성 도구는 부분 클래스를 생성하므로 개발자는 원하는 경우 수동으로 작성된 코드를 별도의 파일로 클래스에 쉽게 추가 할 수 있습니다.