복붙노트

[SCALA] 왜 스칼라 패키지 오브젝트 내부 클래스는 dispreferred입니까?

SCALA

왜 스칼라 패키지 오브젝트 내부 클래스는 dispreferred입니까?

2.10부터 -Xlint 패키지 객체의 내부에 정의 된 클래스에 대해 불평한다. 그런데 왜? 패키지 객체의 내부 클래스를 정의하면 같은 이름을 가진 별도의 패키지 내부의 클래스를 정의 정확히 동일해야, 훨씬 더 편리 예외입니다.

제 생각에는, 스칼라에서 심각한 설계 결함 중 하나는 파일의 최상위 레벨 클래스와 같은 엔티티 (예를 들어, 변수 선언, 함수 정의) 이외의 다른 넣을 수 없다는 것이다. 대신, 별도의 ''패키지 오브젝트 ''(종종 package.scala에서)에 넣어와 그들이 속해 있다는 코드의 나머지 부분과 분리하도록 강요하고 개념적으로 관련 코드가해야하는 기본적인 프로그래밍 규칙을 위반하고 육체적으로뿐만 아니라 관련 될 수있다. 나는 사용자가 그것에 대해 걱정하지 않아도 그래서, 스칼라는 개념적으로는 낮은 수준에서 허용하는 최고 수준에서 아무것도 할 수없는 어떤 이유를 참조하고, 아무것도 자동으로 패키지 오브젝트에 배치됩니다 비 클래스 좋아하지 않는다.

것을 예를 들어, 내 경우에는 내가 패키지 util을가 있고, 그 아래에 나는 (등 util.io, util.text, util.time, util.os, util.math, util.distances) 서브 패키지의 번호를 가지고 의미 적으로 관련된 기능 클래스 때로는 변수 군 이종 모음. 나는 현재 파일에 앉아 패키지 객체 등 모든 다양한 기능 클래스를 저장하는 폴더의 유틸리티 디렉토리에 text.scala이든 또는 io.scala을했다. 이 위대한 작품과 혼합 될 수 있기 때문에 방법은 함수와 클래스의 매우 편리합니다, 예를 들어, 내가 좋아하는 뭔가를 할 수 있습니다 :

package object math {
  // Coordinates on a sphere

  case class SphereCoord(lat: Double, long: Double) { ... }

  // great-circle distance between two points
  def spheredist(a: SphereCoord, b: SphereCoord) = ...

  // Area of rectangle running along latitude/longitude lines
  def rectArea(topleft: SphereCoord, botright: SphereCoord) = ...

  // ...
  // ...

  // Exact-decimal functions
  class DecimalInexactError extends Exception

  // Format floating point value in decimal, error if can't do exactly
  formatDecimalExactly(val num: Double) = ...

  // ...
  // ...
}

이 없다면, 나는 불편 재미 대 클래스에보다는 의미에 의해 따라 코드를 분리해야합니다. 대안은, 나는 가정, 정상적인 개체에 넣어하는 것입니다 - 처음부터 패키지 오브젝트를 갖는 목적을 패배의 종류.

해결법

  1. ==============================

    1.정확하게. 의미는 당신이 패키지 객체 내부 클래스를 정의 호의를 그렇게하면 좋은 이유가 있어야한다, (현재) 동일합니다. 그러나 현실은 (킵 읽기)에는 적어도 하나의 좋은 이유가 없다는 것입니다.

    정확하게. 의미는 당신이 패키지 객체 내부 클래스를 정의 호의를 그렇게하면 좋은 이유가 있어야한다, (현재) 동일합니다. 그러나 현실은 (킵 읽기)에는 적어도 하나의 좋은 이유가 없다는 것입니다.

    그게 어떻게 더 편리? 당신이이 일을하는 경우 :

    package object mypkg {
      class MyClass
    }
    

    당신은 단지뿐만 아니라 다음을 수행 할 수 있습니다 :

    package mypkg {
      class MyClass
    }
    

    당신은 그 과정에서 몇 가지 문자를 절약 할 수 있습니다 :

    자, 좋은 패키지 개체를 바다에 갈 수없는 구체적인 이유는 패키지가 열려있는 동안, 패키지 객체가 아니라는 것이다. 일반적인 시나리오는 코드가 같은 패키지에 클래스를 정의하는 각 프로젝트, 여러 프로젝트 중 파견하는 것입니다. 여기에 문제 없음. 다른 한편으로는, 패키지 개체는 (사양 풋로는 "패키지 당 하나의 패키지 객체가 될 수있다") 폐쇄 (개체처럼)입니다. 다른 말로, 당신은 단지 프로젝트 중 하나의 패키지 오브젝트를 정의 할 수 있습니다. 당신은 두 가지 프로젝트에 동일한 패키지에 대한 패키지의 객체를 정의하려고하면 효과적으로 두 가지로 끝날 것 같은 나쁜 일이 일어날 것 독특한 같은 JVM 클래스의 버전 (N 우리의 경우는 두 가지 "mypkg.class"파일로 끝날 것이다). 사례에 따라, 당신은 패키지 개체의 첫 번째 버전에 정의 된 뭔가를 찾을 수있는 컴파일러 불평없이 종료 될 수 있습니다 또는 "나쁜 상징적 참조"오류, 또는 잠재적으로 런타임 오류. 당신이 알고 있어야하기 때문에 이러한 현상이 패키지 오브젝트의 일반적인 제한 사항입니다. 패키지 객체의 내부 클래스를 정의의 경우, 해결책은 간단하다 :하지 않는다 (주어진 그냥 최고 수준으로 클래스를 정의에 비해 상당한 아무것도 얻을하지 않습니다). 형 aliase, 애송이들이다과 바르 위해, 우리는 지금이 경우는 (객체에서 그들을 정의에 비해) 통 사적 편익 가치가 있는지 여부 무게의 문제이며, 이러한 luxuary이없는 한 다음 않도록주의하십시오 중복 패키지 객체를 정의합니다.

  2. ==============================

    2.나는이 의미 해당 작업이 린트 경고를 생성하는 이유에 좋은 대답을 발견하지 않았습니다. 그분들의이 보풀이 버그입니다. 반드시이 (일반 패키지에 대) 패키지 객체 내부에 위치하지 않는 것이 내가 찾은있는 유일한 것은 기본 구현 (또는 응용 프로그램을 확장)하는 객체입니다.

    나는이 의미 해당 작업이 린트 경고를 생성하는 이유에 좋은 대답을 발견하지 않았습니다. 그분들의이 보풀이 버그입니다. 반드시이 (일반 패키지에 대) 패키지 객체 내부에 위치하지 않는 것이 내가 찾은있는 유일한 것은 기본 구현 (또는 응용 프로그램을 확장)하는 객체입니다.

    -Xlint도 암시 클래스에 대해 불평주의는 패키지 범위에서 선언 할 수는 없지만, 내부 패키지 오브젝트를 선언했다. (암시 적 클래스의 규칙 http://docs.scala-lang.org/overviews/core/implicit-classes.html를 참조하십시오.)

  3. ==============================

    3.나는 중단에 대한 불만이없는 패키지 개체의 모든 장점을 허용 트릭을 알아 냈다. 대신에

    나는 중단에 대한 불만이없는 패키지 개체의 모든 장점을 허용 트릭을 알아 냈다. 대신에

    package object foo {
      ...
    }
    

    넌 할 수있어

    protected class FooPackage {
      ...
    }
    
    package object foo extends FooPackage { }
    

    동일하지만 불만을 작동합니다. 불만 자체가 가짜 것이 분명 기호.

  4. from https://stackoverflow.com/questions/17270003/why-are-classes-inside-scala-package-objects-dispreferred by cc-by-sa and MIT license