추상 함수와 가상 함수의 차이점은 무엇입니까? 어떤 경우에 가상 또는 추상을 사용하는 것이 좋습니다? 가장 좋은 방법은 무엇입니까?
추상 함수와 가상 함수의 차이점은 무엇입니까? 어떤 경우에 가상 또는 추상을 사용하는 것이 좋습니다? 가장 좋은 방법은 무엇입니까?
답변:
추상 함수는 기능을 가질 수 없습니다. 기본적으로 모든 하위 클래스는이 메소드의 자체 버전을 제공해야하지만 상위 클래스에서 구현하려고 시도하는 것은 너무 일반적입니다.
가상 함수 는 기본적으로 외모를 말하고 있습니다. 자식에 충분하거나 충분하지 않을 수있는 기능이 있습니다. 충분하다면이 방법을 사용하고 그렇지 않은 경우 나를 무시하고 고유 한 기능을 제공하십시오.
추상 함수에는 구현이 없으며 추상 클래스에서만 선언 할 수 있습니다. 이렇게하면 파생 클래스가 구현을 제공하게됩니다.
가상 함수는 기본 구현을 제공하며 추상 클래스 또는 비추 상 클래스에 존재할 수 있습니다.
예를 들어 :
public abstract class myBase
{
//If you derive from this class you must implement this method. notice we have no method body here either
public abstract void YouMustImplement();
//If you derive from this class you can change the behavior but are not required to
public virtual void YouCanOverride()
{
}
}
public class MyBase
{
//This will not compile because you cannot have an abstract method in a non-abstract class
public abstract void YouMustImplement();
}
MyBase
클래스는 구현해야 추상적 어떻게 든 클래스를? 나는 이것을 자주하지 않기 때문에 착각 할 수 있습니다. 나는 당신의 예에서 그것을 보지 못합니다.
abstract
수업 만 가능abstract
회원 .abstract
클래스한다는로부터 상속 abstract
클래스 해야 override
그abstract
구성원.abstract
멤버는 암시 적이다virtual
.abstract
멤버는 구현 (제공 할 수 없다 abstract
라고 pure virtual
일부 언어에서).virtual
또는 아닌 수 있습니다 virtual
. abstract
멤버 (즉, 추상적 인 특성, 추상적 인 방법은) 그 자체와 기본 구현을 수행하지 않는 것을 제외하고 즉, 당신은 그것을 대체 할 수 있습니다, 단지 가상의 방법과 같다.
추상 메서드 : 클래스에 추상 메서드가 포함 된 경우 해당 클래스는 추상으로 선언해야합니다. 추상 메소드에는 구현이 없으므로 해당 추상 클래스에서 파생 된 클래스는이 추상 메소드에 대한 구현을 제공해야합니다.
가상 메소드 : 클래스는 가상 메소드를 가질 수 있습니다. 가상 메소드에는 구현이 있습니다. 가상 메서드가있는 클래스에서 상속하면 가상 메서드 를 재정의하고 추가 논리를 제공하거나 논리를 자신의 구현으로 바꿀 수 있습니다.
사용시기 : 경우에 따라 특정 유형에 특정 방법이 있어야한다는 것을 알고 있지만이 방법에 어떤 구현이 필요한지 알 수 없습니다.
이러한 경우이 서명이있는 메소드가 포함 된 인터페이스를 작성할 수 있습니다. 그러나 그러한 경우가 있지만 해당 인터페이스의 구현 자에게 또 다른 일반적인 메소드 (이미 구현을 제공 할 수있는)가 있음을 알고 있으면 추상 클래스를 작성할 수 있습니다. 그런 다음이 추상 클래스에는 추상 메소드 (오버라이드해야 함)와 '공통'논리를 포함하는 다른 메소드가 포함됩니다.
직접 사용할 수는 있지만 상속자가 특정 동작을 변경할 수 있기를 원하지만 필수는 아니지만 가상 메서드를 사용해야합니다.
설명 : 유추로. 잘하면 그것은 당신을 도울 것입니다.
문맥
나는 건물의 21 층에서 일합니다. 그리고 나는 불에 대한 편집증입니다. 세상 어딘가에서 불이 하늘 긁는 도구를 태우고 있습니다. 그러나 운 좋게도 화재시해야 할 일에 대한 지침서가 여기 있습니다.
비상 계단()
기본적으로 FireEscape () 라는 가상 메소드입니다.
가상 방법
이 계획은 상황의 99 %에 매우 적합합니다. 작동하는 기본 계획입니다. 그러나 화재 탈출구가 막히거나 손상 될 가능성이 1 %입니다.이 경우 완전히 조여져 과감한 조치를 취하지 않으면 축배가됩니다. 가상 메소드를 사용하면 다음과 같이 할 수 있습니다. 기본 버전의 FireEscape () 계획을 자체 버전의 계획으로 재정의 할 수 있습니다.
즉, 가상 메소드는 기본 계획을 제공하며, 필요한 경우 대체 할 수 있습니다 . 프로그래머가 적절하다고 생각하면 서브 클래스는 부모 클래스의 가상 메소드를 대체 할 수 있습니다.
추상 방법
모든 조직이 잘 훈련 된 것은 아닙니다. 일부 조직은 소방 훈련을하지 않습니다. 그들은 전반적인 탈출 정책이 없습니다. 모든 사람은 자신을위한 것입니다. 경영진은 기존 정책에만 관심이 있습니다.
즉, 각 사람은 자신의 FireEscape () 메소드를 개발 해야 합니다. 한 사람이 화재 탈출구를 걸어 나갑니다. 다른 사람은 낙하산을 씁니다. 다른 사람은 로켓 추진 기술을 사용하여 건물에서 날아갑니다. 다른 사람이 밖으로 나옵니다. 기본 FireEscape () 계획이있는 한 경영진은 어떻게 탈출 해야하는지 신경 쓰지 않습니다. 그렇지 않은 경우 OHS가 벽돌처럼 조직에 쓰러 질 것입니다. 이것이 추상적 방법입니다.
이 둘의 차이점은 무엇입니까?
추상 메소드 : 하위 클래스는 자체 FireEscape 메소드를 구현 해야 합니다. 가상 메소드를 사용하면 기본 계획이 기다리고 있지만 충분하지 않은 경우 직접 구현 하도록 선택할 수 있습니다 .
이제 그렇게 힘들지 않습니까?
추상 메소드는 구체적인 클래스를 만들기 위해 구현해야하는 메소드입니다. 선언은 추상 클래스에 있으며 추상 메서드가있는 클래스는 추상 클래스 여야하며 구체적인 클래스로 구현해야합니다.
가상 메서드는 재정의를 사용하여 파생 클래스에서 재정의 되어 수퍼 클래스의 동작을 대체 할 수있는 메서드입니다 . 재정의하지 않으면 원래 동작이 나타납니다. 그렇게하면 항상 새로운 행동을 얻게됩니다. 이는 가상 메서드가 아니라 재정의 할 수는 없지만 원래 메서드를 숨길 수는 없습니다. 이것은 new
수정자를 사용하여 수행됩니다 .
다음 예를 참조하십시오.
public class BaseClass
{
public void SayHello()
{
Console.WriteLine("Hello");
}
public virtual void SayGoodbye()
{
Console.WriteLine("Goodbye");
}
public void HelloGoodbye()
{
this.SayHello();
this.SayGoodbye();
}
}
public class DerivedClass : BaseClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
인스턴스화 DerivedClass
하고 SayHello
, 또는를 호출 SayGoodbye
하면 "Hi There"와 "나중에 보자"가 표시됩니다. 전화 HelloGoodbye
하면 "Hello"와 "나중에 보자"가 표시됩니다. SayGoodbye
가상 이기 때문에 파생 클래스로 대체 될 수 있습니다. SayHello
은 숨겨져 있기 때문에 기본 클래스에서 호출하면 원래 메서드를 얻습니다.
추상 메소드는 내재적으로 가상입니다. 인터페이스와 같이 존재해야하는 동작을 정의합니다.
다음 클래스에서 다른 답변을 개선하여이를 단순화했습니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestOO
{
class Program
{
static void Main(string[] args)
{
BaseClass _base = new BaseClass();
Console.WriteLine("Calling virtual method directly");
_base.SayHello();
Console.WriteLine("Calling single method directly");
_base.SayGoodbye();
DerivedClass _derived = new DerivedClass();
Console.WriteLine("Calling new method from derived class");
_derived.SayHello();
Console.WriteLine("Calling overrided method from derived class");
_derived.SayGoodbye();
DerivedClass2 _derived2 = new DerivedClass2();
Console.WriteLine("Calling new method from derived2 class");
_derived2.SayHello();
Console.WriteLine("Calling overrided method from derived2 class");
_derived2.SayGoodbye();
Console.ReadLine();
}
}
public class BaseClass
{
public void SayHello()
{
Console.WriteLine("Hello\n");
}
public virtual void SayGoodbye()
{
Console.WriteLine("Goodbye\n");
}
public void HelloGoodbye()
{
this.SayHello();
this.SayGoodbye();
}
}
public abstract class AbstractClass
{
public void SayHello()
{
Console.WriteLine("Hello\n");
}
//public virtual void SayGoodbye()
//{
// Console.WriteLine("Goodbye\n");
//}
public abstract void SayGoodbye();
}
public class DerivedClass : BaseClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
public class DerivedClass2 : AbstractClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
// We should use the override keyword with abstract types
//public new void SayGoodbye()
//{
// Console.WriteLine("See you later2");
//}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
}
바인딩 은 이름을 코드 단위로 매핑하는 프로세스입니다.
늦은 바인딩 은 이름을 사용하지만 매핑을 연기 함을 의미합니다. 다시 말해, 먼저 이름을 생성 / 멘션하고 일부 후속 프로세스가 해당 이름에 대한 코드 매핑을 처리하도록합니다.
이제 다음을 고려하십시오.
따라서 짧은 대답은 다음과 같습니다. virtual
기계에 대한 늦은 바인딩 명령입니다 (런타임) abstract
. 인간 (프로그래머)에 대한 늦은 바인딩 명령입니다.
즉, 다음을 virtual
의미합니다.
“ 런타임 , 최선을 다하여 적절한 코드를이 이름에 바인딩하십시오 : 검색 ”
반면 abstract
:
“친애하는 프로그래머 여러분 , 최선을 다하여 최선을 다하여 적절한 코드를이 이름에 바인딩하십시오 : 발명 ”
완전성을 위해 과부하 는 다음을 의미합니다.
“ 컴파일러에게 , 최선의 작업을 수행하여 적절한 코드를이 이름에 바인딩하십시오 : 정렬 ”.
가상 방법 :
가상은 우리가 그것을 무시할 수 있음을 의미합니다.
가상 함수에는 구현이 있습니다. 클래스를 상속하면 가상 함수를 재정의하고 자체 논리를 제공 할 수 있습니다.
추상 방법
초록은 반드시 재정의해야 함을 의미합니다.
추상 함수는 구현이 없으며 추상 클래스에 있어야합니다.
선언 만 가능합니다. 이렇게하면 파생 클래스가 해당 클래스의 구현을 제공하게됩니다.
추상 멤버는 암시 적으로 가상입니다. 초록은 일부 언어에서 순수 가상이라고 할 수 있습니다.
public abstract class BaseClass
{
protected abstract void xAbstractMethod();
public virtual void xVirtualMethod()
{
var x = 3 + 4;
}
}
추상적 인 방법은 다음과 같이 정의되는 곳이 있습니다. **
"추상 메소드는 자식 클래스에서 구현해야합니다"
** 나는 같다고 느꼈다.
자식 클래스가 abstract 인 경우 자식 메서드에서 추상 메서드를 구현할 필요는 없습니다 .
1) 추상적 인 방법은 어차피 개인 방법합니다. 2) 추상 방법 캔트 같은 추상 클래스에서 구현 될 수있다.
.. 추상 클래스를 구현하는 경우 기본 추상 클래스의 추상 메서드를 재정의해야합니다. .. 추상 메소드를 구현하는 것은 대체 키워드로. 가상 메소드 와 유사합니다.
상속 된 클래스에서 가상 메소드를 구현할 필요는 없습니다.
----------CODE--------------
public abstract class BaseClass
{
public int MyProperty { get; set; }
protected abstract void MyAbstractMethod();
public virtual void MyVirtualMethod()
{
var x = 3 + 4;
}
}
public abstract class myClassA : BaseClass
{
public int MyProperty { get; set; }
//not necessary to implement an abstract method if the child class is also abstract.
protected override void MyAbstractMethod()
{
throw new NotImplementedException();
}
}
public class myClassB : BaseClass
{
public int MyProperty { get; set; }
//You must have to implement the abstract method since this class is not an abstract class.
protected override void MyAbstractMethod()
{
throw new NotImplementedException();
}
}
위의 예제 대부분은 코드를 사용하며 매우 좋습니다. 나는 그들이 말하는 것에 덧붙일 필요는 없지만, 다음은 코드 / 기술 용어보다는 유추를 사용하는 간단한 설명입니다.
간단한 설명-유추를 사용한 설명
추상 방법
George W Bush를 생각하십시오. 그는 병사들에게 "이라크에서 싸워라"고 말합니다. 그리고 그게 다야. 그가 지정한 것은 싸움이 반드시 이루어져야한다는 것입니다. 그는 그것이 정확히 어떻게 일어날 지를 명시하지 않았다 . 그러나 나는 당신이 그냥 나가서 싸울 수는 없다는 것을 의미합니다. 그것이 정확히 무엇을 의미합니까? 나는 B-52 또는 내 derringer와 싸울 수 있습니까? 이러한 특정 세부 사항은 다른 사람에게 남아 있습니다. 이것은 추상적 인 방법입니다.
가상 방법
David Petraeus는 군대에서 높은 자리에 있습니다. 그는 싸움의 의미를 정의했습니다.
문제는 그것이 매우 일반적인 방법이라는 것입니다. 작동하는 좋은 방법이지만 때로는 구체적이지 않습니다. Petraeus에게 좋은 점은 그의 명령에 여정과 범위가 있다는 것입니다. 그는 특정 요구 사항에 따라 다른 사람들이 "싸움"에 대한 자신의 정의를 변경할 수 있도록 허용했습니다.
Private Job Bloggs는 Petraeus의 명령을 읽고 특정 요구 사항에 따라 자신의 전투 버전을 구현할 수있는 권한을 부여받습니다.
누리 알 말리키도 페트라에 우스로부터 동일한 명령을받습니다. 그는 또한 싸워야한다. 그러나 그는 보병이 아닌 정치인입니다. 분명히 그는 머리에 자신의 정치 적을 쏠 수 없습니다. Petraeus는 그에게 가상 방법을 제공했기 때문에 Maliki는 특정 상황에 따라 자신의 버전의 싸움 방법을 구현할 수 있습니다.
다시 말해서, 가상 방법은 상용구 지침을 제공하지만, 이는 일반적인 지침이며, 특정 상황에 따라 군대 계층 구조의 사람들이 더 구체적으로 만들 수 있습니다.
둘의 차이점
George Bush는 구현 세부 사항을 증명하지 않습니다. 다른 사람이 제공해야합니다. 이것은 추상적 인 방법입니다.
반면에 페트라 우스는 않습니다 구현 세부 정보를 제공하지만 그는 더 나은 뭔가를 가지고 올 수 있다면, 자신의 버전으로 자신의 명령을 무시하는 자신의 부하 직원에 대한 권한을 부여하고있다.
그것이 도움이되기를 바랍니다.
추상 함수 는 본문을 가질 수 없으며 반드시 자식 클래스로 대체되어야합니다.
가상 함수 에는 본문이 있으며 하위 클래스로 대체되거나 대체되지 않을 수 있습니다.
일반적인 객체 지향적 관점에서 :
추상 메소드에 관하여 : 부모 클래스에 추상 메소드를 넣을 때 실제로 당신은 자식 클래스에 대해 말하고 있습니다. 그리고 당신이 그것을 사용하려면 자신을 구현해야합니다!
가상 함수 관련 : 부모 클래스에 가상 메소드를 넣을 때 파생 클래스에 말하고 있습니다. 여기서 당신을 위해 무언가를하는 기능이 있습니다. 이것이 유용한 경우 사용하십시오. 그렇지 않다면 이것을 무시하고 코드를 구현하십시오. 심지어 당신의 코드에서 구현을 사용할 수 있습니다!
이것은 일반 OO에서이 두 개념의 차이점에 대한 철학입니다
C #에는 가상 클래스를 호출하는 것이 없습니다.
기능
요구 사항에 따라 결정할 수 있습니다.
추상 함수 또는 메소드 는 클래스에 의해 노출되는 공개 "작업 이름"이며, 추상 클래스와 함께 그 목적은 주로 개체가 구현해야하는 구조에 대한 개체 디자인의 제약 조건을 제공합니다.
실제로 추상 클래스에서 상속 된 클래스는이 메소드에 구현을 제공해야합니다. 일반적으로 컴파일러는 그렇지 않은 경우 오류를 발생시킵니다.
클래스를 설계 할 때 구현 세부 사항에 초점을 두어 클래스 구조가 구현과 너무 관련되어 있으므로 클래스 간 종속성 및 결합을 작성하는 경우 클래스와 메소드를 사용하는 것이 중요합니다.
가상 함수 또는 메소드 는 단순히 클래스의 공개 동작을 모델링하는 메소드이지만 상속 클래스에서 클래스를 자유롭게 수정할 수 있습니다. 하위 클래스는 해당 동작에 대한 특정 확장을 구현해야 할 수 있기 때문입니다.
그것들 은 객체 지향 패러다임에서 다원주 의의 형태를 나타냅니다 .
좋은 상속 모델을 지원하기 위해 추상 메소드와 가상 함수를 함께 사용할 수 있습니다.
우리는 솔루션의 주요 객체에 대한 추상 구조를 설계 한 다음, 더 전문화되기 쉬운 위치를 찾아 기본 구현을 작성하고,이를 가상으로 만들고, 결국 기본 구현을 특화하여 상속 된 가상 객체를 "재정의"합니다.
여기에 인터페이스, 추상 클래스 및 일반 클래스의 동작을 매우 기본적인 수준으로 볼 수있는 실질적인 예가되기를 희망하는 샘플 코드를 작성하고 있습니다. 데모로 사용하려는 경우 github에서이 코드를 프로젝트로 찾을 수도 있습니다. https://github.com/usavas/JavaAbstractAndInterfaceDemo
public interface ExampleInterface {
// public void MethodBodyInInterfaceNotPossible(){
// }
void MethodInInterface();
}
public abstract class AbstractClass {
public abstract void AbstractMethod();
// public abstract void AbstractMethodWithBodyNotPossible(){
//
// };
//Standard Method CAN be declared in AbstractClass
public void StandardMethod(){
System.out.println("Standard Method in AbstractClass (super) runs");
}
}
public class ConcreteClass
extends AbstractClass
implements ExampleInterface{
//Abstract Method HAS TO be IMPLEMENTED in child class. Implemented by ConcreteClass
@Override
public void AbstractMethod() {
System.out.println("AbstractMethod overridden runs");
}
//Standard Method CAN be OVERRIDDEN.
@Override
public void StandardMethod() {
super.StandardMethod();
System.out.println("StandardMethod overridden in ConcreteClass runs");
}
public void ConcreteMethod(){
System.out.println("Concrete method runs");
}
//A method in interface HAS TO be IMPLEMENTED in implementer class.
@Override
public void MethodInInterface() {
System.out.println("MethodInInterface Implemented by ConcreteClass runs");
// Cannot declare abstract method in a concrete class
// public abstract void AbstractMethodDeclarationInConcreteClassNotPossible(){
//
// }
}
}