왜 그리고 언제 수업을 '정적'으로 만들어야합니까? 클래스에서 '정적'키워드의 목적은 무엇입니까?


47

static여러 언어로 된 멤버 의 키워드는 해당 멤버에 액세스 할 수 있도록 해당 클래스의 인스턴스를 만들지 않아야 함을 의미합니다. 그러나 나는 전체 수업을 만드는 데 대한 정당성을 보지 못했다 static. 왜 그리고 언제 수업을 static해야합니까?

수업을하면 어떤 혜택이 static있습니까? 정적 클래스를 선언 한 후에도 인스턴스화하지 않고 액세스하려는 모든 멤버를 정적으로 선언해야합니다.

예를 들어 Math개발자가 코딩하는 방식에 영향을 미치지 않고 클래스를 정적이 아닌 일반으로 선언 할 수 있습니다. 다시 말해, 클래스를 정적 ​​또는 일반으로 만드는 것은 개발자에게 투명합니다.


Func Prog 스타일의 la Rich Hickey로 코딩하는 경우 유용 할 수 있습니다.
Job

1
내 생각에 정적 클래스는 C #이 언어의 거대한 디자인 결함을 숨기려고하는 목발 일뿐입니다. 이 무의미한 모든 것의 클래스 이데올로기 주위에 언어를 구성 해야하는 이유는 추가 구문을 도입하여 불필요 한 제한을 피할 수 있습니다. C #이 get-go에서 무료 함수를 허용 한 경우 정적 클래스가 필요하지 않습니다.
antred

답변:


32

클래스가 어떻게 사용되는지 사용자에게 분명합니다. 예를 들어 다음 코드를 작성하는 것은 말도 안됩니다.

Math m = new Math();

C #은하지 않습니다 해야 이 금지하지만 더 목적을 제공하지 않기 때문에, 그뿐만 아니라 사용자에게 있습니다. 저를 포함한 특정 사람들은 프로그래밍 언어 (및 API)가 가능한 한 제한적으로 사용해야 잘못 사용하기가 어렵다는 철학을 고수합니다.


3
나는 그 철학에 동의하지 않습니다. 내가 가진 문제는 변화가 필요하다는 것입니다. 따라서 지금까지 제한하는 것이 합리적 일 수 있지만 이러한 제한으로 인해 향후 요구에 대한 개발이 방해됩니다. 또한 기존 시스템 (모든 클래스를 작성하고 봉인하고 고정한 시스템)과 인터페이스하기 위해 사용해야하는 레거시 라이브러리는 사용자가 작성한 코드를 확장하거나 수정할 수있는 방법을 제공하지 않습니다. 수업을 인스턴스화 할 이유가 없다고해서 앞으로 수업이 필요하지 않다는 의미는 아닙니다. 유틸리티 클래스를 정적 ​​화하는 것은 의미가 있지만 미래도 고려하십시오.
SoylentGray

19
@Chad 그러면 라이브러리가 잘못 설계되었습니다. 확장 용으로 설계되지 않은 클래스 확장은 궁극적으로 작동하지 않으므로 sealed처음에 클래스 를 작성하는 것이 가장 좋습니다 . 모든 사람들이이 감정에 동의하는 것은 아니지만 의견이 이에 대해 논의하기에 좋은 장소는 아니라는 점을 인정합니다. 그러나이 static문제 의 경우 자체적으로 포즈를 취하지도 않습니다. 인스턴스화 System.Math결코 의미 가 없습니다 .
Konrad Rudolph

1
@Konard, Math클래스를 정적으로 선언하지 않고 클래스 의 모든 멤버 를 정적으로 선언하면 Math인스턴스화 할 필요없이 클래스를 계속 사용할 수 있습니다.
Saeed Neamati

11
@Saeed-이것은 사실이지만 클래스를 인스턴스화 할 수도 있습니다.이 클래스는 어떤 목적에도 도움이되지 않습니다. Math 클래스 의 인스턴스 로 무엇을해야 합니까? 클래스의 의도를 명시 적으로 보여주기 위해 (인스턴스화가 필요 없거나 원치 않음)으로 표시되어 static있습니다.
Corbin 3 월

3
@Saeed 이것을 돌아 보자 : 나는 당신 이 그것을 잘못 이해 한 것 같아서 나의 대답을 다시 읽도록 제안한다 : 당신의 의견은 나의 대답과 관련이 없다. 나는 당신이 쓸 필요가 있다고 말한 적이 없습니다 new Math().
Konrad Rudolph

24

StackOverflow는이 주제에 대해 큰 토론을합니다 . 쉽게 참조 할 수 있도록 저자 인 Mark S. Rasmussen 을 대신하여 여기에 복사하여 붙여 넣기합니다 .

정적 클래스에 대한 생각을 이전 스레드에서 작성했습니다 .

정적 메소드로 채워진 유틸리티 클래스를 좋아했습니다. 그들은 다른 방법으로 중복 및 유지 관리 지옥을 초래할 수있는 도우미 방법을 크게 통합했습니다. 그것들은 사용하기 쉽고 인스턴스화도없고 폐기도 불필요합니다. 나는 이것이 서비스 지향 아키텍처를 만들기위한 첫 번째 의도하지 않은 시도라고 생각합니다. 그러나 시스템이 성장함에 따라 드래곤들이오고있다.

다형성

우리가 행복하게 울리는 UtilityClass.SomeMethod 메소드가 있다고 가정 해보십시오. 갑자기 기능을 약간 변경해야합니다. 대부분의 기능은 동일하지만 그럼에도 불구하고 두 부분을 변경해야합니다. 정적 메서드가 아닌 경우 파생 클래스를 만들고 필요에 따라 메서드 내용을 변경할 수 있습니다. 정적 방법이므로 할 수 없습니다. 물론, 이전 메소드 이전 또는 이후에 기능을 추가해야하는 경우 새 클래스를 작성하고 그 내부에서 이전 클래스를 호출 할 수 있습니다.

인터페이스 문제

논리적 인 이유로 인터페이스를 통해 정적 메소드를 정의 할 수 없습니다. 정적 메서드를 재정의 할 수 없기 때문에 정적 클래스는 인터페이스에서 전달해야 할 때 쓸모가 없습니다. 이로 인해 전략 패턴의 일부로 정적 클래스를 사용할 수 없습니다. 인터페이스 대신 델리게이트를 전달하여 일부 문제를 해결할 수 있습니다.

테스팅

이것은 기본적으로 위에서 언급 한 인터페이스 문제와 밀접한 관련이 있습니다. 구현을 교환하는 능력이 매우 제한되어 있으므로 프로덕션 코드를 테스트 코드로 바꾸는 데 어려움이 있습니다. 다시 말하지만, 우리는 그것들을 마무리 할 수 ​​있지만 실제 객체 대신 래퍼를 허용하기 위해 코드의 큰 부분을 변경해야합니다.

육성 물방울

정적 메소드는 일반적으로 유틸리티 메소드로 사용되며 유틸리티 메소드는 일반적으로 다른 목적을 갖기 때문에 일관성이없는 기능으로 채워진 큰 클래스로 빠르게 끝나게됩니다. 이상적으로는 각 클래스가 시스템 내에서 단일 목적을 가져야합니다. 그들의 목적이 잘 정의되어 있다면 클래스의 5 배를 훨씬 더 갖고 싶습니다.

파라미터 크리프

우선, 그 귀엽고 순진한 정적 메서드에는 단일 매개 변수가 필요할 수 있습니다. 기능이 커지면 몇 가지 새로운 매개 변수가 추가됩니다. 선택 사항 인 추가 매개 변수가 추가되어 메서드 오버로드를 만들거나 해당 언어를 지원하는 언어로 기본값을 추가합니다. 머지 않아 10 개의 매개 변수를받는 방법이 있습니다. 처음 세 개만 필요하며 매개 변수 4-7은 선택 사항입니다. 그러나 매개 변수 6을 지정하면 7-9도 채워야합니다 ...이 정적 메서드가 수행 한 작업을 수행하는 단일 목적으로 클래스를 만들었 으면 필요한 매개 변수를 사용하여이를 해결할 수 있습니다 생성자 및 사용자가 속성을 통해 선택적 값을 설정하거나 여러 개의 상호 종속 값을 동시에 설정하는 방법을 허용합니다. 또한,

아무 이유없이 소비자에게 클래스 인스턴스를 작성하도록 요구

가장 일반적인 주장 중 하나는 왜 우리 클래스의 소비자가이 단일 메소드를 호출하기 위해 인스턴스를 작성하고 나중에 인스턴스를 사용하지 않아도되는 인스턴스를 작성해야 하는가입니다. 클래스의 인스턴스를 만드는 것은 대부분의 언어에서 매우 저렴한 작업이므로 속도는 문제가되지 않습니다. 소비자에게 추가 코드 줄을 추가하는 것은 앞으로 훨씬 더 유지 보수가 쉬운 솔루션의 기초를 마련하는 데 드는 비용이 적습니다. 마지막으로, 인스턴스 생성을 피하려면 클래스의 싱글 톤 래퍼를 작성하여 쉽게 재사용 할 수 있습니다. 이렇게하면 클래스가 무국적이어야한다는 요구 사항이됩니다. 상태가없는 경우에도 모든 것을 처리하는 정적 래퍼 메서드를 만들면서도 장기적으로 모든 이점을 얻을 수 있습니다. 드디어,

시스 만이 절대 거래

물론 정적 메소드를 싫어하는 경우에는 예외가 있습니다. 부 풀릴 위험이없는 진정한 유틸리티 클래스는 정적 메소드 인 System.Convert에 대한 훌륭한 사례입니다. 프로젝트가 향후 유지 보수에 대한 요구 사항이없는 일회성이라면 전체 아키텍처는 중요하지 않습니다. 정적이든 비 정적이든 실제로 중요하지 않습니다. 그러나 개발 속도는 중요합니다.

표준, 표준, 표준!

인스턴스 메소드를 사용해도 정적 메소드를 사용할 수 없으며 그 반대도 마찬가지입니다. 차별화의 이유가 있고 표준화되어있는 한. 다른 구현 방법으로 비즈니스 계층을 살펴 보는 것보다 나쁘지 않습니다.


12
흠, 여기에 전체 답변을 복사하여 붙여 넣을 것임을 모르겠습니다. "토론"을 언급 한 후 자신의 경험을 공유 할 수있는 다른 견해를 포함시킬 수있는 링크와 구절이 있을까요?
Corbin 3 월

2
"Sith만이 절대적 문제를 다루고있다"-나는 이전에 그런 식으로 사용 된 것을 보지 못했다. 그러나 그것은 완벽하다. 나를 롤로 만들었습니다.
Brook

4
@ 코빈 : 마크 좋은 대답했다. 나는 그에게 신용을 주며 쉽게 참조 할 수 있도록 복사 / 붙여 넣기를했습니다. 이 문제에 대한 나의 견해는 마크의 견해와 일치합니다. 토론을 시작하는 것 외에는 귀하의 의견이 중요하지 않습니다.
Rick

1
@ 릭 : 복사 된 답변은 꽤 길며 그것을 표현하면 분명히 도움이됩니다. "이 게시물이 보여주는 것처럼 실제로 유용하지 않고 해를 입힐 수도 있습니다."와 같은 문장은 내가 찾던 정보가 아니라는 것을 알기 때문에 빨리 건너 뛸 수 있습니다.
blubb

@Simon : LOL I 1+ 님의 게시물입니다. 너무 멍청한 것에 대해 논쟁을 그만두려는 시도에 동의합니다. :) 원래 포스터가 답장 / 복사 및 붙여 넣기 기능을 찾았 으면 좋겠습니다.
Rick

16

내가 언급 한 사람을 다른 놀랐어요 static클래스가 허용하는 확장 메서드를 안전하게 (를 포함하여 기존 유형의 확장 - 인터페이스에 메소드 정의를 추가를 소유하지 않은 것을). 예를 들어 스칼라의 내용은

trait MyFoo {
  def foo: Int
  def plusFoo(a: Int) = foo + a
}

C #에서 다음과 같이 표현 될 수 있습니다.

public interface IMyFoo {
  int Foo();
}

public static class MyFooExtensions {
  public static int PlusFoo(this IMyFoo f, int a) {
    return f.Foo() + a;
  }
}

건초 더미에서 바늘을 찾았습니다. +1
Saeed Neamati 16:27에

3

나에게 정적 클래스 (C #에서)는 함수를 호출하는 것과 같습니다.

예를 들어

public static string DoSomething(string DoSomethingWithThisString){}

문자열을 전달하고 문자열을 다시 가져옵니다. 이 방법에는 모든 것이 포함되어 있습니다. 멤버 변수 등에 액세스 할 수 없음

솔직히, 주로 나를 위해 사용하면 코드 줄이 줄어 들었습니다.

왜 이렇게:

MyClass class = new MyClass();
String s = class.DoSomething("test");

내가 할 수있을 때 :

String s = MyClass.DoSomething("test");

따라서 클래스가 필요없는 무언가를하고 싶을 때 입력을 줄이려는 경우 정적 클래스를 사용합니다.

Mark S. 포인트는 유효하지만 유틸리티 메소드가있는 경우 척하기가 더 쉽다는 것을 하나의 라이너로 참조하는 함수를 호출하고 있습니다.

그것은 간단 할 수 있지만, 대부분 내가 사용한 방법 static입니다.


1
new MyClass (). DoSomething ( "test")는 여전히 유효합니다. 나는 이것을 테스트 데이터 빌더에 많이 사용합니다.
JoanComasFdz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.