IT이야기

Scala(및 Java)에서 클래스와 유형의 차이점

cyworld 2021. 10. 28. 19:20
반응형

Scala(및 Java)에서 클래스와 유형의 차이점은 무엇입니까?


스칼라

Scala에서 클래스와 유형의 차이점은 어디에서 관찰할 수 있으며 이 구분이 중요한 이유는 무엇입니까?

언어 디자인 관점에서만 고려하는 것입니까, 아니면 Scala를 프로그래밍할 때 "실용적인" 영향을 미치나요?

아니면 유형 시스템의 "경계 확보"가 기본 입니까 ( Nothing, Null마음에 와요)?

자바

위에서 언급한 고려 사항/차이점/문제 중 몇 가지를 Java에서도 인식할 수 있습니까?


( 언어에 구애받지 않는 소개로 Type과 Class의 차이점무엇입니까?참조하십시오 .)


"유형"이라고 하면 주로 정적 유형을 의미한다고 가정하겠습니다. 하지만 곧 동적 유형에 대해 이야기하겠습니다.

정적 유형은 정적으로 입증될 수 있는 프로그램 부분의 속성입니다(정적은 "실행하지 않고"를 의미함). 정적으로 유형이 지정된 언어에서 모든 표현식에는 작성 여부에 관계없이 유형이 있습니다. 예를 들어, Cish "int x = a * b + c - d"에서 a,b,c,d에는 유형이 있고, a * b에는 유형이 있고, a * b + c에는 유형이 있고, a * b + c -d에는 유형이 있습니다. 그러나 우리는 유형으로 x에만 주석을 달았습니다. Scala, C#, Haskell, SML 및 F#과 같은 다른 언어에서는 그마저도 필요하지 않습니다.

정확히 어떤 속성을 증명할 수 있는지는 유형 검사기에 따라 다릅니다.

반면에 Scala 스타일 클래스는 객체 집합에 대한 사양일 뿐입니다. 이 사양은 일부 유형 정보를 포함하고 메서드 본문 및 개인 필드 등과 같은 많은 구현 및 표현 세부 정보를 포함합니다. Scala에서 클래스는 또한 일부 모듈 경계를 지정합니다.

많은 언어에는 유형이 있지만 클래스가 없으며 많은 언어에는 클래스가 있지만 (정적) 유형이 없습니다.

유형과 클래스 사이에는 몇 가지 관찰 가능한 차이점이 있습니다. List[String]은 유형이지만 클래스가 아닙니다. 스칼라에서 목록은 클래스이지만 일반적으로 유형이 아닙니다(실제로는 더 높은 종류의 유형입니다). C#에서 List는 어떤 종류의 유형도 아니며 Java에서는 "원시 유형"입니다.

스칼라는 구조적 유형을 제공합니다. {def foo : Bar}는 클래스에 관계없이 Bar를 반환하는 foo 메서드가 있는 것으로 증명된 모든 객체를 의미합니다. 유형이지만 클래스는 아닙니다.

유형 매개변수를 사용하여 유형을 추상화할 수 있습니다. def foo[T](x : T) = ...를 작성할 때 foo T의 본문 내부에는 유형이 있습니다. 그러나 T는 클래스가 아닙니다.

유형은 Scala에서 가상이 될 수 있지만(즉, "추상 유형 구성원") 클래스는 오늘날 Scala에서 가상이 될 수 없습니다(비록 가상 클래스를 인코딩하는 보일러플레이트 무거운 방법이 있지만 https://wiki.scala-lang.org/display/ SIW/가상 클래스 디자인 )

이제 동적 유형입니다. 동적 유형은 특정 작업을 수행하기 전에 런타임이 자동으로 확인하는 개체의 속성입니다. 동적으로 유형이 지정된 클래스 기반 OO 언어에는 유형과 클래스 간에 강력한 상관 관계가 있습니다. 리플렉션 및 캐스팅과 같이 동적으로만 확인할 수 있는 작업이 있는 Scala 및 Java와 같은 JVM 언어에서도 동일한 일이 발생합니다. 이러한 언어에서 "유형 삭제"는 대부분의 개체의 동적 유형이 해당 클래스와 동일함을 의미합니다. 더 많거나 적습니다. 예를 들어, 런타임이 Array[Int]와 Array[String]의 차이를 구분할 수 있도록 일반적으로 지워지지 않는 배열의 경우에는 그렇지 않습니다. 하지만 "런타임이 자동으로 검사하는 개체의 동적 유형 속성"이라는 광범위한 정의를 기억하십시오. 리플렉션을 사용하면 모든 개체에 메시지를 보낼 수 있습니다. 개체가 해당 메시지를 지원하면 모든 것이 제대로 작동합니다. 따라서 오리처럼 꽥꽥거릴 수 있는 모든 객체를 클래스가 아니더라도 동적 유형으로 말하는 것이 합리적입니다. 이것이 Python 및 Ruby 커뮤니티에서 "오리 타이핑"이라고 부르는 것의 본질입니다. 또한 대부분의 언어에서 런타임이 자동으로 숫자를 확인하여 0으로 나누지 않도록 하는 의미에서 "0"도 광범위한 정의에 따라 동적 유형입니다. 0(또는 0이 아닌)을 정적 유형으로 만들어 이를 정적으로 증명할 수 있는 언어는 거의 없습니다. 비록 수업은 아니지만. 이것이 Python 및 Ruby 커뮤니티에서 "오리 타이핑"이라고 부르는 것의 본질입니다. 또한 대부분의 언어에서 런타임이 자동으로 숫자를 확인하여 0으로 나누지 않도록 하는 의미에서 "0"도 광범위한 정의에 따라 동적 유형입니다. 0(또는 0이 아닌)을 정적 유형으로 만들어 이를 정적으로 증명할 수 있는 언어는 거의 없습니다. 비록 수업은 아니지만. 이것이 Python 및 Ruby 커뮤니티에서 "오리 타이핑"이라고 부르는 것의 본질입니다. 또한 대부분의 언어에서 런타임이 자동으로 숫자를 확인하여 사용자가 0으로 나누지 않도록 하는 의미에서 "0"도 광범위한 정의에 따라 동적 유형입니다. 0(또는 0이 아닌)을 정적 유형으로 만들어 이를 정적으로 증명할 수 있는 언어는 거의 없습니다.

마지막으로 다른 사람들이 언급했듯이 구현 세부 사항으로 클래스가 없는 int와 같은 유형, 약간 특별하지만 클래스가 있고 없을 수 있는 Null 및 Any와 같은 유형, 없는 것과 같은 유형이 있습니다. t는 클래스는 고사하고 어떤 값도 가지고 있습니다.


좋아, 물어볼게... James가 좋은 대답을 했으니 나는 다른 전술을 시도하고 좀 더 현실적인 관점을 제시할 것이다.

일반적으로 클래스는 인스턴스화할 수 있는 것입니다 . 싱글톤 객체(scala) 특성(Scala) 및 인터페이스(Scala)도 일반적으로 클래스로 간주됩니다. 싱글톤이 여전히 인스턴스화되고(컴파일러 생성 코드를 통해) 인터페이스가 하위 클래스의 일부로 인스턴스화될 수 있기 때문에 이는 의미가 있습니다.

이것은 우리를 두 번째 요점으로 이끕니다. 클래스는 대부분의 객체 지향 언어에서 기본 디자인 단위입니다(자바스크립트와 같은 프로토타입 기반 언어는 아님). 다형성과 서브클래싱은 둘 다 클래스 측면에서 정의됩니다. 클래스는 네임스페이스와 가시성 컨트롤도 제공합니다.


유형은 매우 다른 짐승이며 시스템이 표현할 수 있는 모든 가능한 값에는 하나 이상의 유형이 있으며 이러한 유형은 때때로 클래스와 동일할 수 있습니다. 예를 들면 다음과 같습니다.

(Int) => String // both the type and class are Function1[Int,String]
"hello world" // class and type are String    

또한 Scala와 Java 간에 몇 가지 흥미로운 차이점이 있습니다.

7 // both the class and type are Int in Scala
  // in Java there's no class and the type is Integer.TYPE

println("hello world") // the return type is Unit, of class Unit
                       // Java has void as a type, but no corresponding class

error("oops") // the type and class are both "Nothing"

수업이 전혀 아닌 정말 재미있는 유형입니다. 예를 들어, this.type항상 의 고유한 유형을 나타냅니다 this. 단일 인스턴스에 고유하며 동일한 클래스의 다른 인스턴스와도 호환되지 않습니다.

추상 유형과 유형 매개변수도 있습니다. 예를 들어:

type A // 'A' is an undetermined abstract type
       // to be made concrete in a subclass

class Seq[T] { ... } // T is a type, but not a class

Seq is interesting as it's a class, but not a type. More accurately, it's a "type constructor"; something that will construct a valid type when supplied with the necessary type parameter. Another term for type constructors is "higher kinded types", I personally don't like this term, as "type constructor" encourages me to think in terms of supplying types like any other form of argument - a mental model that has served me well for Scala.

"higher-kinded" rightly implies that Seq has a "kind", which is * => *, this notation states that Seq will take a single type and yield a single type (this is similar to curried notation for describing functions). By way of comparison, the kind of Map is * => * => * because it takes two type parameters.


A type can be useful by itself, without any instances. One example for this is called "phantom type". Here is an example for Java: http://michid.wordpress.com/2008/08/13/type-safe-builder-pattern-in-java/

In that example we have public static class Initializer<HA, HB>, where HA and HB take some types (represented by the abstract classes TRUE and FALSE), without ever beeing instantiated.

I hope this shows that types and classes are something different, and that types can be useful by itself.


(Java only) I'd say, a type is a set of objects. Object o is type X, if o is a member of set X. Type X is a subtype of Y, if set X is a subset of Y.

For every class C (not interface) there is a set of objects, created from new C(...). Interestingly, we rarely cares about this set. (but every object does belong to a set like this, a fact that may be useful)

For every class C, there is a type t(C), generally refered to as "the type C", which is the set of all objects that can be created from new S(...) where S is C or a subclass of C.

Similarly, for every interface I, there is a type t(I), "the type I", which is the set of all objects that can be created from new S(...) where S implements I.

Obviously, if class S is a subclass of C, type S is a subtype of type C. Similar for interface I

There is a null type, which is the empty set. The null type is a subtype of every type.

There is a set of all objects, which is the type Object. It's a super type of every type.

So far, this formalism is pretty useless. A type is basically the same as a class or an interface, and the subtype relation is basically the subclass/subinterface relation. The triviality is a good thing, the language was understandable! But entering generics, there are more complicated types, and operations like unions and intersections of types. Types are no longer only classes and interfaces, and subtype relations are much richer and harder to understand.

ReferenceURL : https://stackoverflow.com/questions/5031640/what-is-the-difference-between-a-class-and-a-type-in-scala-and-java

반응형