interface, abstract class concepts

I came across an example, like below, where an interface is defined. then an abstract class is defined that implements this interface.

Now the concrete implementation class, both inherits and implements, base class and interface respectively.

Questions -

1. does it need to implement both?
2. the way I understand this is, this is being done for code reuse. so that any common implementation goes in the abstract class and concrete implementation don't have to provide their own implementation. based on that, why not just have abstract class?

public interface IWork {
       string workerName {get; set;}
       
       int CountHours();
       
       void DoWork();
}

public abstract class Work : IWork {

      public string workerName {get; set;}
     
      public int CountHourse(){
         //do some calculation
         //return result;
      }

      Public abstract void DoWork();
}

public class PrimaryWork : Work : IWork {
   
      public override void DoWork(){
            //do something
      }
}
novice programmerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

 
Chris StanyonCommented:
PrimaryWork doesn't need to implement IWork explicitly. It already implements it through the Abstract.

There are several reasons to use an Interface, but one of the biggest advantages is Multi Inheritance - you can implement several Interfaces, but only inherit from 1 class.

By implementing your Interface into an Abstract class, you've given your concrete class the shape of the interface along with some / all of the default implementation of the Interface.
1
 
it_saigeDeveloperCommented:
In addition to the above, whatever the parent class implements/inherits, the child *also* implements/inherits...  The difference being that, in practice, some implementations can be defined in *only* the parent class, some implementations can be defined in *either* the parent and/or the child and finally, other implementations can be defined in *only* the child class; e.g. -
using System;
using System.Collections.Generic;

namespace EE_Q29076271
{
	class Program
	{
		static List<Animal> animals = new List<Animal>
		{
			new Bear { Name = "Larry" },
			new Fish { Name = "Goldie" },
			new Dog { Name = "Spot" },
			new Cat { Name = "Tiny" }
		};

		static void Main(string[] args)
		{
			animals.ForEach(animal =>
			{
				if (!string.IsNullOrEmpty(animal.MakeNoise))
					Console.WriteLine(animal.MakeNoise);
				else
					Console.WriteLine($"{animal.Name} is a {animal.GetType().ToString().Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries)[1]} and does not make noise...");
				animal.PerformFlip();
				Console.WriteLine();
			});
			Console.ReadLine();
		}
	}

	// I am an abstract class, I can only be inherited, you cannot create a new instance of me directly.
	abstract class Animal : IAnimal, ICircus
	{
		// I am marked as virtual which means that any class that inherits my enclosing class can override my implementation.
		public virtual string MakeNoise { get { return string.Empty; } }

		// I am a public property of the enclosing class, I cannot be overridden.  I am only defined by this class.
		public string Name { get; set; }

		// I am an abstract method, any class that inherits my enclosing class must implement me.
		public abstract void PerformFlip();

		public override string ToString()
		{
			return $"{Name}";
		}
	}

	// As with the abstract class above, I can only be implemented, you cannot create a new instance of me directly
	interface IAnimal
	{
		// I must be implemented by anything that implements this interface
		string Name { get; set; }
	}

	// As with the abstract class above, I can only be implemented, you cannot create a new instance of me directly
	interface ICircus
	{
		// I must be implemented by anything that implements this interface
		void PerformFlip();
	}

	// I inherit from Animal
	class Bear : Animal
	{
		// Overriding the Animal.MakeNoise method to provide my own implementation
		public override string MakeNoise { get { return $"{ToString()} ROARS!!!"; } }

		// Implementing the Animal.PerformFlip method
		public override void PerformFlip()
		{
			Console.WriteLine($"It's tough but {Name} is flipping!!!");
		}
	}

	// I inherit from Animal
	class Fish : Animal
	{
		// Implementing the Animal.PerformFlip method
		public override void PerformFlip()
		{
			Console.WriteLine($"{Name} loves flipping!!!");
		}
	}

	// I inherit from Animal
	class Dog : Animal
	{
		// Overriding the Animal.MakeNoise method to provide my own implementation
		public override string MakeNoise { get { return $"{ToString()} BARKS!!!"; } }

		// Implementing the Animal.PerformFlip method
		public override void PerformFlip()
		{
			Console.WriteLine($"{Name} loves flipping!!!");
		}
	}

	// I inherit from Animal
	class Cat : Animal
	{
		// Overriding the Animal.MakeNoise method to provide my own implementation
		public override string MakeNoise { get { return $"{ToString()} MEOWS!!!"; } }

		// Implementing the Animal.PerformFlip method
		public override void PerformFlip()
		{
			Console.WriteLine($"{Name} always lands on their feet when they flip!!!");
		}
	}
}

Open in new window

Which produces the following output -Capture.PNGNOTE:   In regards to method's being defined in *only* or *either* the parent/child classes.  As stated this is in practice.  The language does allow for inheritance classes to define it's own method(s) that *hides* (or *shadows*, for VB.NET) the inherited definition(s); e.g. -Capture.PNGImplementation:
using System;
using System.Collections.Generic;

namespace EE_Q29076271
{
	class Program
	{
		static List<Animal> animals = new List<Animal>
		{
			new Bear { Name = "Larry" },
			new Fish { Name = "Goldie" },
			new Dog { Name = "Spot" },
			new Cat { Name = "Tiny" }
		};

		static void Main(string[] args)
		{
			animals.ForEach(animal =>
			{
				if (!string.IsNullOrEmpty(animal.MakeNoise))
					Console.WriteLine(animal.MakeNoise);
				else
					Console.WriteLine($"{animal.Name} is a {animal.GetType().ToString().Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries)[1]} and does not make noise...");
				animal.PerformFlip();
				Console.WriteLine();
			});
			Console.ReadLine();
		}
	}

	// I am an abstract class, I can only be inherited, you cannot create a new instance of me directly.
	abstract class Organism
	{
		// I am an abstract method, any class that inherits my enclosing class must implement me.
		public abstract string MakeNoise { get; }
	}

	// I am an abstract class, I can only be inherited, you cannot create a new instance of me directly.
	abstract class Animal : Organism, IAnimal, ICircus
	{
		// I am marked as sealed which means that no inheritor can override my implementation, they must hide or shadow it.
		public sealed override string MakeNoise { get { return string.Empty; } }

		// I am a public property of the enclosing class, I cannot be overridden.  I am only defined by this class.
		public string Name { get; set; }

		// I am an abstract method, any class that inherits my enclosing class must implement me.
		public abstract void PerformFlip();

		public override string ToString()
		{
			return $"{Name}";
		}
	}

	// As with the abstract class above, I can only be implemented, you cannot create a new instance of me directly
	interface IAnimal
	{
		// I must be implemented by anything that implements this interface
		string Name { get; set; }
	}

	// As with the abstract class above, I can only be implemented, you cannot create a new instance of me directly
	interface ICircus
	{
		// I must be implemented by anything that implements this interface
		void PerformFlip();
	}

	// I inherit from Animal
	class Bear : Animal
	{
		// Hiding the Animal.MakeNoise method to provide my own implementation
		new public string MakeNoise { get { return $"{ToString()} ROARS!!!"; } }

		// Implementing the Aminal.PerformFlip method
		public override void PerformFlip()
		{
			Console.WriteLine($"It's tough but {Name} is flipping!!!");
		}
	}

	// I inherit from Animal
	class Fish : Animal
	{
		// Hiding the Animal.Name property to provide my own implementation.
		new public string Name { get; set; }

		// Implementing the Animal.PerformFlip method
		public override void PerformFlip()
		{
			Console.WriteLine($"{Name} loves flipping!!!");
		}
	}

	// I inherit from Animal
	class Dog : Animal
	{
		// Hiding the Animal.MakeNoise method to provide my own implementation
		new public string MakeNoise { get { return $"{ToString()} BARKS!!!"; } }

		// Implementing the Animal.PerformFlip method
		public override void PerformFlip()
		{
			Console.WriteLine($"{Name} loves flipping!!!");
		}
	}

	// I inherit from Animal
	class Cat : Animal
	{
		// Hiding the Animal.MakeNoise method to provide my own implementation
		new public string MakeNoise { get { return $"{ToString()} MEOWS!!!"; } }

		// Implementing the Animal.PerformFlip method
		public override void PerformFlip()
		{
			Console.WriteLine($"{Name} always lands on their feet when they flip!!!");
		}
	}
}

Open in new window

Which would produce the same output as above.

But in these cases the implementation's are very specialized.

This type of pattern fly's against common practices which dictate that your code is maintainable.  The most common practice for base classes and interfaces is contract/rules driven, where the base classes and interfaces define the contracts and/or rules that the inheritors *must* (some might say should) follow.

-saige-
1

Experts Exchange Solution brought to you by ConnectWise

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.