Abstract Method in Non Abstract Class

≡放荡痞女 提交于 2021-02-04 09:18:24

问题


I want to know the reason behind the design of restricting Abstract Methods in Non Abstract Class (in C#).

I understand that the class instance won't have the definition and thus they wont be callable, but when static methods are defined,they are excluded from the instance too. Why abstract methods are not handled that way, any specific reason for the same?

They could be allowed in concrete class and the deriving class can be forced to implement methods, basically that is what, is done in case of abstract methods in an abstract class.


回答1:


First, I think that what you're asking doesn't logically make sense. If you have abstract method, it basically means that the method is unfinished (as @ChrisSinclair pointed out). But that also means the whole class is unfinished, so it also has to be abstract.

Or another way to put it: if you had abstract method on a class that wasn't abstract, that would mean you had a method that cannot be called. But that means the method is not useful, you could remove it and it would all work the same.

Now, I'll try to be more concrete by using an example: imagine the following code:

Animal[] zoo = new Animal[] { new Monkey(), new Fish(), new Animal() };

foreach (Animal animal in zoo)
    animal.MakeSound();

Here, Animal is the non-abstract base class (which is why I can put it directly into the array), Monkey and Fish are derived from Animal and MakeSound() is the abstract method. What should this code do? You didn't state that clearly, but I can imagine few options:

  1. You can't call MakeSound() on a variable typed as Animal, you can call it only using a variable typed as one of the derived classes, so this is a compile error.

    This is not a good solution, because the whole point of abstract is to be able to treat instances of derived classes as the base class, and still get behavior that's specific to the derived class. If you want this, just put a normal (no abstract, virtual or override) method into each derived class and don't do anything with the base class.

  2. You can't call MakeSound() on an object whose runtime type is actually Animal, so this is a runtime error (an exception).

    This is also not a good solution. C# is a statically typed language and so it tries to catch errors like “you can't call this method” at compile time (with obvious exceptions like reflection and dynamic), so making this into a runtime error wouldn't fit with the rest of the language. Besides, you can do this easily by creating a virtual method in the base class that throws an exception.

To sum up, you want something that doesn't make much sense, smells of bad design (base class that behaves differently than its derived classes) and can be worked around quite easily. These are all sings of a feature that should not be implemented.




回答2:


So, you want to allow

class C { abstract void M(); }

to compile. Suppose it did. What do you then want to happen when someone does

new C().M();

? You want an execution-time error? Well, in general C# prefers compile-time errors to execution-time errors. If you don't like that philosophy, there are other languages available...




回答3:


I think you've answered your own question, an abstract method isn't defined initially. Therefore the class cannot be instanciated. You're saying it should ignore it, but by definition when adding an abstract method you're saying "every class created from this must implement this {abstract method}" hence the class where you define the abstract class must also be abstract because the abstract method is still undefined at that point.




回答4:


You can achieve what you want using "virtual" methods but using virtual methods can lead to more runtime business logic errors as a develop is not "forced" to implement the logic in the child class.

I think there's a valid point here. An abstract method is the perfect solution as it would "enforce" the requirement of defining the method body in children.

I have come across many many situations where the parent class had to (or it would be more efficient to) implement some logic but "Only" children could implement rest of the logic"

So if the opportunity was there I would happily mix abstract methods with complete methods.

@AakashM, I appreciate C# prefers compile time errors. So do I. And so does anybody. This is about thinking out-of-the-box.

And supporting this will not affect that.

Let's think out of the box here, rather than saying "hurrah" to big boy decisions.

C# compiler can detect and deny someone of using an abstract class directly because it uses the "abstract" keyword.

C# also knows to force any child class to implement any abstract methods. How? because of the use of the "abstract" keyword.

This is pretty simple to understand to anyone who has studied the internals of a programming language.

So, why can't C# detect an "abstract" keyword next to a method in a normal class and handle it at the COMPILE TIME.

The reason is it takes "reworking" and the effort is not worth supporting the small demand.

Specially in an industry that lacks people who think out of the boxes that big boys have given them.




回答5:


The abstract class may contain abstract member. There is the only method declaration if any method has an abstract keyword we can't implement in the same class. So the abstract class is incompleted. That is why the object is not created for an abstract class.

Non-abstract class can't contain abstract member.

Example:

namespace InterviewPreparation
{
   public abstract class baseclass
    {
        public abstract void method1(); //abstract method
        public abstract void method2(); //abstract method
        public void method3() { }  //Non- abstract method----->It is necessary to implement here.
    }
    class childclass : baseclass
    {
        public override void method1() { }
        public override void method2() { }
    }
    public class Program    //Non Abstract Class
    {
        public static void Main()
        {
            baseclass b = new childclass(); //create instance
            b.method1();
            b.method2();
            b.method3();
        }
    }

}



回答6:


It's still not clear why you would want that, but an alternative approach could be to force derived classes to provide a delegate instance. Something like this

class MyConcreteClass
{
  readonly Func<int, DateTime, string> methodImpl;

  // constructor requires a delegate instance
  public MyConcreteClass(Func<int, DateTime, string> methodImpl)
  {
    if (methodImpl == null)
      throw new ArgumentNullException();

    this.methodImpl = methodImpl;
  }

  ...
}

(The signature string MethodImpl(int, DateTime) is just an example, of course.)

Otherwise, I can recommend the other answers to explain why your wish probably isn't something which would make the world better.



来源:https://stackoverflow.com/questions/12581070/abstract-method-in-non-abstract-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!