Scala에서 컴패니언 객체를 갖는 이유는 무엇입니까?


답변:


82

컴패니언 객체는 기본적으로 "정적 유사"메서드를 넣을 수있는 장소를 제공합니다. 또한 컴패니언 객체 또는 컴패니언 모듈은 private 멤버를 포함하여 클래스 멤버에 대한 전체 액세스 권한을 갖습니다.

컴패니언 객체는 팩토리 메소드와 같은 것을 캡슐화하는 데 좋습니다. 대신 예를 들어,이, 필요로 Foo하고 FooFactory모든 곳에서, 당신은 공장의 책임에 동반자 개체를 포획하여 클래스를 가질 수 있습니다.


61

컴패니언 객체는 클래스의 모든 인스턴스에 공통적 인 상태 및 메서드를 저장하는 데 유용 하지만 정적 메서드 나 필드를 사용하지 않습니다 . 상속을 통해 재정의 할 수있는 일반 가상 메서드를 사용합니다. Scala에는 진정으로 정적이 없습니다. 이것을 사용할 수있는 많은 방법이 있지만 여기에 간단한 예가 있습니다.

abstract class AnimalCounter
{
    var animals = 0

    def name: String

    def count()
    {
        animals += 1
        println("%d %ss created so far".format(animals, name))
    }
}

abstract class Animal
{
    def companion: AnimalCounter
    companion.count()
}

object Dog extends AnimalCounter
{
    val name = "dog"
}

class Dog extends Animal
{
    def companion = Dog
}

object Cat extends AnimalCounter
{
    val name = "cat"
}

class Cat extends Animal
{
    def companion = Cat
}

이 출력을 생성합니다.

scala> new Dog
1 dogs created so far

scala> new Cat
1 cats created so far

scala> new Dog
2 dogs created so far

scala> new Cat
2 cats created so far

1
비슷한 그림도 여기에서 찾을 수 있습니다 : daily-scala.blogspot.sk/2009/09/companion-object.html
xhudik

30

... 수반되는 클래스에 대한 정적 팩토리 메서드 (DP가 아님)를 저장하는 것이 좋습니다. 오버로드 된 팩토리 메소드의 이름을 apply (/ ... /)로 지정하면 클래스를 생성 / 초기화 할 수 있습니다.

  1. 'new'없이 (그다지 중요하지 않음)

  2. 다른 가능한 매개 변수 세트 사용 (Bloch가 생성자 텔레 스코핑에 대해 Effective Java에서 작성한 것과 비교)

  3. 추상 (수반 된) 클래스 대신 만들려는 파생 클래스를 결정할 수있는 기능

예제 코드 :

abstract class AbstractClass;
class RealThing(s: String) extends AbstractClass;
class AlternativeThing(i: Int) extends AbstractClass;
object AbstractClass {
  def apply(s: String) = {
    new RealThing(s)
  }
  def apply(i: Int) = {
    new AlternativeThing(i)
  }
}

// somewhere else you can
val vs = AbstractClass("asdf")  // gives you the RealThing wrapped over string
val vi = AbstractClass(123)  // gives you AlternativeThing wrapped over int

객체 / 기본 클래스 AbstractXxxxx는 나쁘지 않기 때문에 호출하지 않습니다. 마치 추상적 인 것을 만드는 것과 같습니다. 그 이름에 진정한 의미를 부여하십시오. 불변, 메소드 덜, 케이스 클래스 사용을 고려하고 추상 기본 클래스를 봉인하십시오.


2
RealThing그리고 AlternativeThing클래스는해야 private(가) 사용하는 사용자를 강제로 생성자 AbstractClass의 공장을 가지고 있습니다. class AlternativeThing private(i: Int) extends AbstractClass
metch

@ [Szymon Jachim] Scala 추상 클래스는 다중 상속을 지원하지 않습니다. 그렇다면 컴파일러가 왜 그것을 허용합니까?
user2441441

19

Saem이 답장 에서 말한 것 외에도 Scala 컴파일러는 암시 적 변환 도 찾습니다. 해당 컴패니언 객체 (소스 또는 대상)에서 유형의 을 검색하므로 변환을 가져올 필요가 없습니다.

Scala의 일반 프로그래밍에서 싱글 톤 객체의 이유에 대해 다음과 같이 말합니다.

1 장에서 언급했듯이 Scala가 Java보다 객체 지향적 인 한 가지 방법은 Scala의 클래스가 정적 멤버를 가질 수 없다는 것입니다. 대신 Scala에는 단일 객체가 있습니다 (65 페이지).


3

저는 항상 컴패니언 객체를 스칼라에서 기능적 코드와 객체 지향 코드를 작성 하는 다리 로 간주합니다 . 많은 경우 입력을 받아 처리 결과를 제공하는 순수 함수가 필요합니다. 이러한 관련 함수를 동반 객체에 배치하면 내 코드 위에 빌드하는 것뿐만 아니라 나 자신을 위해 쉽게 찾고 사용할 수 있습니다.

또한 아무것도하지 않고 싱글 톤 패턴을 작성할 수있는 언어 제공 기능입니다. 이것은 JVM의 수명 동안 위임자를 캡슐화하기 위해 싱글 톤이 필요할 때 특히 유용합니다. 예를 들어 기본 Java 구현 기반 위임자를 캡슐화하고 API 소비자가 순수한 세상에 살도록 할 수있는 Scala에서 간단한 HTTP 클라이언트 라이브러리를 작성합니다.


0

같은 파일에 동일한 이름으로 클래스와 객체를 정의하면 컴패니언 클래스와 객체라고합니다. Scala는 JAVA 키워드로 static이 없습니다. Scala에서 static을 동반 클래스 및 객체로 대체 할 수 있습니다.

자세한 내용 은 스칼라 프로그래밍의 기사 클래스 및 객체 키워드 를 확인하십시오.


-1

처음에는 정적 메서드와 비 정적 메서드 메서드를 명확하게 구분하고 싱글 톤 클래스를 만드는 간단한 방법도 제공합니다.

또한 다른 클래스 및 / 또는 특성에서 메서드를 상속 할 수 있으며, 이는 Java 정적 메서드로 수행 할 수 없으며 매개 변수로 전달할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.