Scala Object 의 구체 적 인 사용(소결)

16433 단어 ScalaObject
머리말
앞에서 Scala Methods 를 배 웠 고,이어서 Scala 의 Object 를 배 웠 습 니 다.
2.개체
Object 는 Scala 에 두 가지 의미 가 있 습 니 다.자바 에 서 는 하나의 인 스 턴 스 를 대표 합 니 다.Scala 에 서 는 하나의 키워드 입 니 다.이 편 은 먼저 object 를 하나의 인 스 턴 스 로 보고 대상 을 하나의 유형 에서 다른 유형 으로 바 꾸 는 방법 을 보 여 줍 니 다.그 다음 에 하나의 대상 을 만 드 는 방법 을 보 여 줍 니 다.Scala 에 가방 대상 도 존재 합 니 다.Scala 에 서 는 다음 과 같은 정의 가 자주 있 습 니 다.

type Throwable = java.lang.Throwable
type Exception = java.lang.Exception
type Error = java.lang.Error
type Seq[+A] = scala.collection.Seq[A]
val Seq = scala.collection.Seq
type 정 의 를 사용 하면 코드 를 더욱 간결 하 게 할 수 있 습 니 다.동반 대상 을 사용 하여 정적 방법 을 만 들 수 있 고 동반 대상 은 클래스 대상 을 만 들 때 new 키 워드 를 사용 하지 않 아 도 됩 니 다.다음 과 같 습 니 다.

val siblings = List(Person("Kim"), Person("Julia"), Person("Kenny"))
2.1 대상 전환
1.문제 설명
동적 생 성 대상 과 같은 인 스 턴 스 를 하나의 유형 에서 다른 유형 으로 바 꿔 야 합 니 다.
2.해결 방안
asInstanceOf 방법 으로 유형 전환 을 진행 합 니 다.다음 lookup 방법 으로 돌아 오 는 대상 은 Recognizer 대상 으로 전 환 됩 니 다.

val recognizer = cm.lookup("recognizer").asInstanceOf[Recognizer]
이상 코드 는 자바 에서 다음 과 같 습 니 다.

Recognizer recognizer = (Recognizer)cm.lookup("recognizer");
asInstanceOf 방법 은 Any 클래스 에 정의 되 어 있 기 때문에 모든 클래스 에서 이 방법 을 사용 할 수 있 습 니 다.
3.토론
동적 프로 그래 밍 에 서 는 하나의 클래스 에서 다른 클래스 로 전환 해 야 합 니 다.예 를 들 어 Spring 프레임 워 크 에서 applicationContext 파일 을 사용 하여 Bean 을 초기 화 합 니 다.

// open/read the application context file
val ctx = new ClassPathXmlApplicationContext("applicationContext.xml")
// instantiate our dog and cat objects from the application context
val dog = ctx.getBean("dog").asInstanceOf[Animal]
val cat = ctx.getBean("cat").asInstanceOf[Animal]
디지털 형식 전환 을 할 때 도 asInstanceOf 방법 을 사용 할 수 있다.

자바 와 의 대화 가 필요 할 때 asInstanceOf 방법 을 사용 할 수 있 습 니 다.

val objects = Array("a", 1)
val arrayOfObject = objects.asInstanceOf[Array[Object]]
AJavaClass.sendObjects(arrayOfObject)
자바 와 유사 하 며,유형 전환 은 ClassCastException 이상 을 던 질 수 있 습 니 다.

try/catch 를 사용 하여 이 문 제 를 해결 할 수 있 습 니 다.
2.2 자바 의 class 와 대응 하 는 방법
1.문제 설명
API 가 클 라 스 대상 을 전달 해 야 할 때 자바 에 서 는.class 를 사용 할 수 있 지만 스칼라 에 서 는 통 하지 않 습 니 다.
2.해결 방안
Scala 의 classOf 방법 을 사용 하면 다음 과 같 습 니 다.

val info = new DataLine.Info(classOf[TargetDataLine], null)
자바 에 서 는 다음 과 같이 사용 합 니 다.

info = new DataLine.Info(TargetDataLine.class, null);
classOf 방법 은 Predef 대상 에 정의 되 어 있 기 때문에 import 없 이 직접 사용 할 수 있 습 니 다.
3.토론
이 방법 은 반 사 를 배우 기 시작 할 수 있 습 니 다.다음 예제 에서 String 류 를 방문 할 수 있 는 방법 입 니 다.

2.3 대상 을 정 하 는 클래스
1.문제 설명
Scala 에 서 는 표시 할 필요 가 없 는 성명 형식 입 니 다.가끔 은 대상 의 클래스 나 형식 을 인쇄 하여 Scala 의 작업 체 제 를 알 고 싶 습 니 다.
2.해결 방안
대상 의 getClass 방법 을 사용 하여 Scala 가 자동 으로 값 을 부여 하 는 유형 을 확인 할 수 있 습 니 다.가 변 적 인 매개 변수 작업 절 차 를 알 아야 할 때 getClass 방법 을 사용 하여 상황 에 따라 유형 도 다 릅 니 다.

def printAll(numbers: Int*) {
  println("class: " + numbers.getClass)
}
여러 개의 매개 변 수 를 사용 하여 printAll 방법 을 호출 하 는 것 과 매개 변 수 를 사용 하지 않 고 printAll 방법 을 호출 하 는 것 은 결과 가 다 릅 니 다.

스칼라 의 XML 라 이브 러 리 를 처리 할 때 이 방법 은 매우 효과 적 입 니 다.서로 다른 상황 에서 처리 하 는 클래스 를 알 수 있 습 니 다.다음 과 같 습 니 다.

탭 에 하위 클래스 가 포함 되 어 있 습 니 다.

탭 에
탭 을 추가 하면 그 결 과 는 다음 과 같 습 니 다.

3.토론
IDE 에서 대상 의 종 류 를 알 수 없 으 면 getClass 방법 으로 대상 종 류 를 가 져 올 수 있 습 니 다.

2.4 사용 대상 시작 응용
1.문제 설명
main 방법 으로 프로그램 을 시작 하거나 스 크 립 트 에 입 구 를 제공 하려 고 합 니 다.
2.해결 방안
응용 프로그램 을 시작 하 는 데 는 두 가지 방법 이 있 는데 하 나 는 응용 프로그램 을 계승 하 는 것 이 고,다른 하 나 는 대상 을 정의 하고 main 방법 을 정의 하 는 것 이다.
첫 번 째 방법 에 대해 그 통용 방법 은 다음 과 같다.


object Hello extends App {
  println("Hello, world")
}
이 때 object 내 문 구 는 자동 으로 실 행 됩 니 다.두 번 째 방법 은 main 방법 을 정의 하 는 것 입 니 다.

object Hello2 {
  def main(args: Array[String]) {
    println("Hello, world")
  }
}  
3.토론
상기 두 가지 방법 중 모두 object 를 통 해 응용 을 시작 합 니 다.
2.5 Object 를 사용 하여 단일 예 만 들 기
1.문제 설명
단일 대상 을 만 들 려 고 합 니 다.
2.해결 방안
object 키 워드 를 사용 하여 단일 대상 을 만 듭 니 다.

object Hello2 {
  def main(args: Array[String]) {
    println("Hello, world")
  }
}  
CashRegister 는 object 로 정의 되 기 때문에 하나의 인 스 턴 스 만 있 고 호출 된 방법 은 자바 의 정적 방법 에 해당 합 니 다.다음 과 같이 호출 됩 니 다.

object Main extends App {
  CashRegister.open
  CashRegister.close
}
도구 방법 을 만 들 때 도 이 방법 은 유효 합 니 다.

import java.util.Calendar
import java.text.SimpleDateFormat

object DateUtils {
  // as "Thursday, November 29"
  def getCurrentDate: String = getCurrentDateTime("EEEE, MMMM d")
  
  // as "6:20 p.m."
  def getCurrentTime: String = getCurrentDateTime("K:m aa")
  
  // a common function used by other date/time functions
  private def getCurrentDateTime(dateTimeFormat: String): String = {
    val dateFormat = new SimpleDateFormat(dateTimeFormat)
    val cal = Calendar.getInstance()
    dateFormat.format(cal.getTime())
  }
}
방법 은 object 에 정의 되 어 있 기 때문에 DateUtils 를 직접 사용 하여 이 방법 을 호출 할 수 있 습 니 다.예 를 들 어 자바 에서 정적 방법 을 호출 하 는 것 과 같 습 니 다.

DateUtils.getCurrentDate
DateUtils.getCurrentTime
actors 를 사용 할 때 단일 대상 은 다시 사용 할 수 있 는 메 시 지 를 만 들 수 있 습 니 다.메 시 지 를 받 아들 이 고 보 낼 수 있 는 actor 가 있다 면 다음 과 같은 방법 으로 단일 예 를 만 들 수 있 습 니 다.

case object StartMessage
case object StopMessage
이 대상 들 은 메시지 로 전달 되 며,actor 에 전 달 될 수 있 습 니 다.

inputValve ! StopMessage
outputValve ! StopMessage
3.토론
동반 대상 을 사용 할 때 한 가지 유형 은 비정 상 방법 도 있 고 정태 적 인 방법 도 있 을 수 있다.
2.6 동반 대상 을 사용 하여 정적 구성원 만 들 기
1.문제 설명
클래스 를 위 한 인 스 턴 스 방법 과 클래스 방법 을 만 들 려 고 하지만 Scala 에는 static 키워드 가 없습니다.
2.해결 방안
class 에서 비정 상 구성원 을 정의 하고 object 에서 정적 구성원 을 정의 합 니 다.대상 과 클래스 는 같은 이름 을 가지 고 같은 파일 에 있어 야 합 니 다.이 대상 을 반생 대상 이 라 고 합 니 다.
이 방법 을 사용 하면 정적 구성원(필드 와 방법)을 만 들 수 있 습 니 다.

// Pizza class
class Pizza (var crustType: String) {
  override def toString = "Crust type is " + crustType
}

// companion object
object Pizza {
  val CRUST_TYPE_THIN = "thin"
  val CRUST_TYPE_THICK = "thick"
  def getFoo = "Foo"
}
Pizza 클래스 와 Pizza 대상 은 같은 파일 에 있 습 니 다(Pizza.scala).Pizza 대상 의 구성원 은 자바 클래스 의 정적 구성원 과 같 습 니 다.

println(Pizza.CRUST_TYPE_THIN)
println(Pizza.getFoo)
너 도 일반적인 방법 에 따라 피자 대상 을 만 들 수 있다.

var p = new Pizza(Pizza.CRUST_TYPE_THICK)
println(p)
3.토론
class 와 object 는 같은 이름 을 가지 고 같은 파일 에서 class 에서 비정 상 구성원 을 정의 합 니 다.object 에서 정 의 된 것 은 정적 구성원 입 니 다.
class 와 그 동반 대상 은 서로 상대방 의 개인 구성원 을 방문 할 수 있 습 니 다.예 를 들 어 아래 object 의 double 방법 은 class 의 개인 변수 secret 에 접근 할 수 있 습 니 다.

class Foo {
  private val secret = 2
}

object Foo {
  // access the private class field 'secret'
  def double(foo: Foo) = foo.secret * 2
}

object Driver extends App {
  val f = new Foo
  println(Foo.double(f)) // prints 4
}
다음 class 클래스 의 비정 상 방법 은 동반 대상 의 정적 개인 변 수 를 방문 할 수 있 습 니 다.

class Foo {
  // access the private object field 'obj'
  def printObj { println(s"I can see ${Foo.obj}") }
}

object Foo {
  private val obj = "Foo's object"
}

object Driver extends App {
  val f = new Foo
  f.printObj
}
2.7 상용 코드 를 가방 대상 에 넣 기
1.문제 설명
클 라 스 나 object 가 필요 없 이 방법,필드,다른 코드 를 패키지 단계 에 두 고 싶 습 니 다.
2.해결 방안
패키지 대상 아래 에 코드 를 배치 합 니 다.예 를 들 어,코드 를 com.hust.grid.leesf.model 에 의 해 모든 종 류 를 사용 할 수 있 도록 패키지 에 넣 으 려 면 com/hust/grid/leesf/model 디 렉 터 리 에 있 는 package.scala 파일 을 만 듭 니 다.package.scala 에서 패키지 성명 에서 model 을 제거 하고 이름 으로 가방 을 만 듭 니 다.대체로 아래 와 같다

package com.hust.grid.leesf

package object model {
다른 코드 는 model 에 놓 여 있 습 니 다.다음 과 같 습 니 다.

package com.hust.grid.leesf

package object model {
  // field
  val MAGIC_NUM = 42

  // method
  def echo(a: Any) { println(a) }
  
  // enumeration
  object Margin extends Enumeration {
    type Margin = Value
    val TOP, BOTTOM, LEFT, RIGHT = Value
  }
  
  // type definition
  type MutableMap[K, V] = scala.collection.mutable.Map[K, V]
  
  val MutableMap = scala.collection.mutable.Map
}
이때,com.hust.grid.leesf.model 패키지 아래 클래스,대상,인터페이스 등에 서 상기 정 의 된 필드,방법 등 을 임의로 방문 할 수 있 습 니 다.

package com.hust.grid.leesf.model

object MainDriver extends App {
  // access our method, constant, and enumeration
  echo("Hello, world")
  echo(MAGIC_NUM)
  echo(Margin.LEFT)
  // use our MutableMap type (scala.collection.mutable.Map)
  val mm = MutableMap("name" -> "Al")
  mm += ("password" -> "123")
  for ((k,v) <- mm) printf("key: %s, value: %s
", k, v) }
3.토론
가장 의 심 스 러 운 것 은 패키지 대상 을 어디 에 두 었 는 지,가방 이름과 대상 명 이다.
코드 를 com.hust.grid.leesf.model 가방 에서 보 려 면 package.scala 를 com/hust/grid/leesf/model 디 렉 터 리 에 두 고 package.scala 에 서 는 가방 이름 이 다음 과 같 아야 합 니 다.

package com.hust.grid.leesf
그리고 model 을 대상 으로 합 니 다.

package object model {
마지막 으로 대체로 다음 과 같다.

package com.hust.grid.leesf

package object model {
가방 에 매 거 진 형식,상수,암시 적 변환 을 저장 할 수 있 습 니 다.
2.8 new 키 워드 를 사용 하지 않 고 대상 인 스 턴 스 를 만 듭 니 다.
1.문제 설명
new 키 워드 를 사용 하지 않 고 대상 을 만 들 때 Scala 코드 는 상대 적 으로 간결 해 보 입 니 다.다음 과 같 습 니 다.

val a = Array(Person("John"), Person("Paul"))
2.해결 방안
두 가지 방법 이 있어 요.
  • 클래스 생 성 대상 을 만 든 다음 에 apply 방법 을 정의 합 니 다.그의 서명 은 구조 방법 서명 과 같 습 니 다
  • 클래스 를 case 클래스 로 정의 합 니 다Person 대상 에 반생 대상 을 정의 한 다음 apply 방법 을 정의 하고 인 자 를 받 아들 입 니 다.
    
    class Person {
      var name: String = _
    }
    
    object Person {
      def apply(name: String): Person = {
        var p = new Person
        p.name = name
        p
      }
    }
    이제 뉴 키 워드 를 사용 하지 않 고 Person 대상 을 만 들 수 있 습 니 다.
    
    val dawn = Person("Dawn")
    val a = Array(Person("Dan"), Person("Elijah"))
    Scala 컴 파 일 러 는 짝 짓 기 대상 중의 apply 를 특수 처리 하여 new 키 워드 를 사용 하지 않 고 대상 을 만 들 수 있 도록 합 니 다.
    클래스 를 case 클래스 로 정의 하고 해당 하 는 매개 변 수 를 받 아들 입 니 다.
    
    case class Person (var name: String)
    현재 다음 과 같은 방법 으로 대상 을 만 들 수 있 습 니 다.
    
    val p = Person("Fred Flinstone")
    Scala 는 케이스 클래스 의 동반 대상 을 위해 apply 방법 을 만 듭 니 다.
    3.토론
    컴 파일 러 는 동반 대상 의 apply 를 특수 처리 합 니 다.이것 은 Scala 의 문법 사탕 입 니 다.
    
    val p = Person("Fred Flinstone")
    상기 코드 는 다음 과 같은 코드 로 바 뀔 것 이다.
    
    val p = Person.apply("Fred Flinstone")
    apply 방법 은 공장 방법 입 니 다.Scala 의 이 문법 사탕 은 new 키 워드 를 사용 하지 않 고 대상 을 만 들 수 있 습 니 다.
    반생 대상 에 여러 개의 apply 방법 을 만 들 수 있 습 니 다.이것 은 여러 개의 구조 함수 에 해당 합 니 다.
    
    class Person {
      var name = ""
      var age = 0
    }
    
    object Person {
      // a one-arg constructor
      def apply(name: String): Person = {
        var p = new Person
        p.name = name
        p
      }
    
      // a two-arg constructor
      def apply(name: String, age: Int): Person = {
        var p = new Person
        p.name = name
        p.age = age
        p
      }
    }
    다음 방법 으로 대상 을 만 들 수 있 습 니 다.
    
    val fred = Person("Fred")
    val john = Person("John", 42)
    케이스 클래스 에 여러 개의 구조 함 수 를 만 들 기 위해 서 는 케이스 클래스 뒤의 논 리 를 알 아야 합 니 다.
    scala 컴 파일 러 를 사용 하여 case 클래스 를 컴 파일 할 때,Person$.class 와 Person.class 파일 두 개 를 생 성 합 니 다.javap 를 사용 하여 Person$.class 파일 을 컴 파일 할 때 출력 은 다음 과 같 습 니 다.

    Person 대상 으로 돌아 가 는 apply 방법 을 포함 하고 있 습 니 다.
    
    public Person apply(java.lang.String);
    String 은 case 클래스 의 name 에 대응 합 니 다.
    
    case class Person (var name: String)
    javap 명령 을 사용 하면 Person.class 에서 name 을 위 한 getter 와 setter 함 수 를 볼 수 있 습 니 다.

    다음 코드 에는 케이스 클래스 와 apply 방법 이 존재 합 니 다.
    
    // want accessor and mutator methods for the name and age fields
    case class Person (var name: String, var age: Int)
    
    // define two auxiliary constructors
    object Person {
      def apply() = new Person("<no name>", 0)
      def apply(name: String) = new Person(name, 0)
    }
    name 과 age 는 모두 var 이기 때문에 getter 와 setter 를 생 성하 고 object 에서 두 개의 apply 함 수 를 정의 하기 때문에 다음 과 같은 세 가지 방식 으로 Person 대상 을 생 성 할 수 있 습 니 다.
    
    object Test extends App {
      val a = Person()
      val b = Person("Al")
      val c = Person("William Shatner", 82)
      println(a)
      println(b)
      println(c)
      // test the mutator methods
      a.name = "Leonard Nimoy"
      a.age = 82
      println(a)
    }
    그 결 과 는 다음 과 같다.
    
    Person(<no name>,0)
    Person(Al,0)
    Person(William Shatner,82)
    Person(Leonard Nimoy,82)
    2.9 apply 를 사용 하여 공장 방법 을 실현 한다.
    1.문제 설명
    하위 클래스 가 어떤 유형의 대상 을 만들어 야 하 는 지,그리고 한 곳 에서 만 대상 을 만 들 수 있 도록 공장 방법 을 실현 하고 싶 습 니 다.
    2.해결 방안
    동반 대상 의 apply 방법 을 사용 하여 공장 방법 을 실현 할 수 있 으 며,공장 실현 알고리즘 을 apply 방법 에 배치 할 수 있 습 니 다.
    Animal 공장 을 만 들 고 Cat 과 Dog 로 돌아 가 Animal 류 의 동반 대상 에서 apply 방법 을 실현 하려 면 다음 과 같은 방식 으로 다른 대상 을 만 들 수 있 습 니 다.
    
    val cat = Animal("cat") // creates a Cat
    val dog = Animal("dog") // creates a Dog
    우선 Animal trait 를 만들어 야 합 니 다.
    
    trait Animal {
      def speak
    }
    그 다음 에 같은 파일 에 동반 대상 을 만 들 고 Animal 을 실현 하 는 클래스 를 만 들 며 적당 한 apply 방법 을 만 듭 니 다.
    
    object Animal {
      private class Dog extends Animal {
        override def speak { println("woof") }
      }
      
      private class Cat extends Animal {
        override def speak { println("meow") }
      }
      
      // the factory method
      
      def apply(s: String): Animal = {
        if (s == "dog") new Dog
        else new Cat
      }
    }
    그리고 다음 문 구 를 사용 하여 서로 다른 대상 을 만 들 수 있 습 니 다.
    
    val cat = Animal("cat") // creates a Cat
    val dog = Animal("dog") // creates a Dog
    3.토론
    apply 방법 을 사용 하지 않 으 면 다음 과 같은 getAnimal 방법 으로 이 기능 을 실현 할 수 있 습 니 다.
    
    // an alternative factory method (use one or the other)
    def getAnimal(s: String): Animal = {
      if (s == "dog") return new Dog
      else return new Cat
    }
    그리고 다음 과 같은 방법 으로 다른 대상 을 만 들 수 있 습 니 다.
    
    val cat = Animal.getAnimal("cat") // returns a Cat
    val dog = Animal.getAnimal("dog") // returns a Dog
    이상 의 두 가지 방법 은 모두 실행 가능 하 다.
    3.총화
    이 편 은 스칼라 의 object 와 그 에 상응하는 용법 을 배 웠 는데 스칼라 의 실제 프로 그래 밍 에서 도 매우 광범 위 하 게 응용 되 었 다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기