抽象方法和虚拟方法有什么区别?在哪些情况下,建议使用抽象方法或虚拟方法?哪一种是最好的方法?
当前回答
抽象方法是一种必须实现才能生成具体类的方法。声明在抽象类中(任何具有抽象方法的类都必须是抽象类),并且必须在具体类中实现。
虚拟方法是一种可以在派生类中使用重写重写的方法,替换超类中的行为。如果不覆盖,则获得原始行为。如果你这样做,你总会得到新的行为。这与不能重写但可以隐藏原始方法的非虚拟方法相反。这是使用新修改器完成的。
请参见以下示例:
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”和“See you later”。如果我打电话给HelloGoodbye,我会收到“你好”和“再见”。这是因为SayGoodbye是虚拟的,可以被派生类替换。SayHello只是隐藏的,所以当我从基类调用它时,我会得到原始方法。
抽象方法是隐式虚拟的。它们定义了必须存在的行为,更像是一个接口。
其他回答
抽象函数不能有主体,必须由子类重写
虚函数将有一个主体,并且可以或不可以被子类重写
抽象函数(方法):
● 抽象方法是用关键字abstract声明的方法。
● 它没有身体。
● 它应该由派生类实现。
● 如果方法是抽象的,那么类应该是抽象的。
虚拟函数(方法):
● 虚方法是用关键字virtual声明的方法,它可以通过使用override关键字由派生类方法重写。
● 是否重写它取决于派生类。
抽象方法是一种必须实现才能生成具体类的方法。声明在抽象类中(任何具有抽象方法的类都必须是抽象类),并且必须在具体类中实现。
虚拟方法是一种可以在派生类中使用重写重写的方法,替换超类中的行为。如果不覆盖,则获得原始行为。如果你这样做,你总会得到新的行为。这与不能重写但可以隐藏原始方法的非虚拟方法相反。这是使用新修改器完成的。
请参见以下示例:
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”和“See you later”。如果我打电话给HelloGoodbye,我会收到“你好”和“再见”。这是因为SayGoodbye是虚拟的,可以被派生类替换。SayHello只是隐藏的,所以当我从基类调用它时,我会得到原始方法。
抽象方法是隐式虚拟的。它们定义了必须存在的行为,更像是一个接口。
必须始终重写抽象函数。
因此:
抽象函数-当继承者必须提供自己的实现时虚拟-由继承人决定
在这里,我写了一些示例代码,希望这可能是一个非常实际的例子,可以从非常基本的层面上看到接口、抽象类和普通类的行为。如果您想将其用作演示,也可以在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(){
//
// }
}
}