수업 또는 추상 수업에서 상속합니다
-
03-07-2019 - |
문제
공통 기능을 위해 기본 클래스에서 상속 받기를 원하는 여러 클래스가있는 경우 클래스 나 추상 클래스를 사용하여 기본 클래스를 구현해야합니까?
해결책
그것은 당신이 기본 클래스를 인스턴스화하고 싶지 않다면, 그것을 추상적으로 만드십시오. 그렇지 않으면 정상적인 클래스로 두십시오.
다른 팁
기본 클래스가 인스턴스화되지 않아야한다면 추상 클래스로 만드십시오. 기본 클래스를 인스턴스화해야한다면 추상적으로 만들지 마십시오.
이 예에서는 기본 클래스에 구체적인 의미가 없으므로 기본 클래스를 추상화하는 것이 합리적입니다.
abstract class WritingImplement
{
public abstract void Write();
}
class Pencil : WritingImplement
{
public override void Write() { }
}
그러나이 다음 예에서는 기본 클래스가 어떻게 구체적인 의미를 갖는지 알 수 있습니다.
class Dog
{
public virtual void Bark() { }
}
class GoldenRetriever : Dog
{
public override void Bark() { }
}
그것은 모두 꽤 주관적입니다. 특정 영역의 요구에 따라 꽤 좋은 판단을 내릴 수 있어야합니다.
문제의 기본 클래스가 파생되지 않고 자체적으로 존재하는 것이 합리적입니까? 대답이 예라면 정규 수업이어야합니다. 그렇지 않으면 추상 클래스 여야합니다.
제안 :
- 인터페이스를 만드십시오.
- 기본 클래스에서 인터페이스를 구현하십시오.
- 기본 클래스를 초록이 아닌 실제 클래스로 만드십시오 (이유는 아래 참조).
추상 클래스 대신 실제 클래스를 선호하는 이유는 추상 클래스를 인스턴스화 할 수 없으므로 향후 옵션을 제한하기 때문입니다. 불필요하게. 예를 들어, 나중에 나는 기본 클래스가 제공 한 상태와 방법이 필요할 수 있지만 상속 할 수 없으며 인터페이스를 구현할 필요가 없습니다. 기본 클래스가 추상적 인 경우 운이 좋지 않지만 기본 클래스가 일반 클래스라면 기본 클래스의 인스턴스를 만들어 다른 클래스의 구성 요소로 유지하고 인스턴스를 재사용 할 수 있습니다. 제공된 상태/방법.
그렇습니다. 이것은 자주 발생하지 않지만 요점은 다음과 같습니다. 기본 클래스를 추상화하면 이유가 없을 때 이런 종류의 재사용/솔루션을 방지합니다.
이제 기본 클래스를 인스턴스화하는 것이 어떻게 든 위험 할 것이라면, 그것을 추상적으로 만들거나, 가능하다면 덜 위험하게 만드십시오. ;-)
은행 계좌처럼 생각하십시오.
"계정"이라는 일반적인 추상 기본 계정을 만들 수 있습니다. 이는 고객 세부 정보와 같은 기본 정보를 보유합니다.
그런 다음 "SavingAccount"또는 "DebitAccount"라는 두 개의 파생 클래스를 만들 수 있으며, 이는 기본 클래스 동작의 혜택을받는 동안 고유 한 특정 동작을 가질 수 있습니다.
이는 고객이 저축 계좌 또는 직불 계좌를 가져야하는 상황이며, 일반 "계정"은 실제 세계에서 설명이없는 계정을 가지고 있지 않기 때문에 허용되지 않습니다.
필요에 대해 유사한 시나리오를 만들 수 있다면 초록이 갈 길입니다.
초록 클래스는 부분적으로 구현 된 클래스를위한 것입니다.
그 자체로는 추상 클래스의 인스턴스를 갖는 것이 합리적이지 않으므로 파생되어야합니다. 기본 클래스를 만들 수 있기를 원한다면 추상적 일 수 없습니다.
나는 추상 클래스를 모든 하위 클래스에 공통적이기 때문에 일부 회원이 미리 정의 된 인터페이스로 생각하고 싶습니다.
이것을 다른 방식으로 생각하십시오
내 기본 클래스가 자신의 완전한 개체입니까?
대답이 아니오라면 추상적으로 만드십시오. 그렇다면 구체적인 클래스로 만들고 싶을 것입니다.
기본 클래스를 자체적으로 호출 할 계획이 없다면 추상 클래스로 정의해야합니다.
기본 클래스가 자체적으로 구현되기를 원하는지 여부에 따라 다릅니다.
추상적 인 클래스로서, 당신은 그것으로부터 객체를 만들 수 없습니다.
예를 들어 초록 클래스는 사전 정의 된 기능에 적합합니다. 예를 들어, 클래스가 노출되어야하는 최소한의 정확한 동작을 알고 있지만 수행하는 데 사용해야하는 데이터 또는 정확한 구현이 아닙니다.
abstract class ADataAccess
{
abstract public void Save();
}
정상 (비 초록) 클래스는 비슷한 것들에 좋을 수 있지만 구현 세부 사항을 알아야합니다.
public class DataAccess
{
public void Save()
{
if ( _is_new )
{
Insert();
}
else if ( _is_modified )
{
Update();
}
}
}
또한 인터페이스 (개별 또는 클래스에서 추상적이든 아니든)를 사용하여 동일한 종류의 프로토 타입 정의를 정의 할 수 있습니다.
interface ISaveable
{
void Save();
void Insert();
void Update();
}
class UserAccount : ISavable
{
void ISavable.Save() { ... }
void ISavable.Insert() { ... }
void ISavable.Update() { ... }
}
또 다른 옵션은 제네릭을 사용하는 것일 수 있습니다
class GenDataAccess<T>
{
public void Save()
{
...
}
}
이 모든 방법을 사용하여 클래스와 함께 작업 할 특정 프로토 타입을 정의 할 수 있습니다. 코드 A가 코드 B와 대화 할 수 있는지 확인하는 방법. 물론 위의 모든 것을 원하는 것과 혼합하고 일치시킬 수 있습니다. 명확한 올바른 방법은 없지만 인터페이스와 추상 클래스를 정의한 다음 인터페이스를 참조하는 것을 좋아합니다. 이렇게하면 최대의 유연성을 유지하면서 더 높은 수준의 클래스에서 "배관"에 대한 사고 요구 사항 중 일부가 제거됩니다. (인터페이스를 갖는 것은 추상 기본 클래스를 사용해야하는 요구 사항을 없애지 만 옵션으로 남겨 둡니다).
많은 사람들이 기본 OO 수업을 다시 해결해야한다고 생각합니다.
OOA/OOD의 기본 기본 원리는 더 이상 추상적이지 않을 때까지 초록 초록을 추상적으로하는 것입니다. 당신이 보는 것이 추상화라면, 그렇게하십시오. 그것이 당신의 ooa/ood가 이미 당신에게 말한 것입니다. 그러나 "코드"가 추상적인지 아닌지 궁금해하는 경우, 그 용어가 무엇을 의미하는지 알지 못하고 기본 OOA/OOD/OOP를 다시 배우게됩니다 :-)
디자인 패턴과 고조파 이론을 배워야 할 때까지, 이것은 OO 디자인에 엄청나게 도움이 될 것입니다!