interfaces

I came across phrase "It's always better to program against interface than concrete types".

can someone elaborate on this a little, with some examples.
novice programmerAsked:
Who is Participating?
 
ste5anSenior DeveloperCommented:
D'oh! Little he said.. in short:

namespace ConsoleCS
{
    using System;

    public class Duck
    {
        public void MakeNoise()
        {
            Console.WriteLine("quack.");
        }
    }

    public class Dog
    {
        public void MakeNoise()
        {
            Console.WriteLine("bark.");
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            DoSomething(new Dog());
            DoSomething(new Duck());
            Console.WriteLine("Done.");
            Console.ReadLine();
        }

        static void DoSomething(Dog animal)
        {
            animal.MakeNoise();
        }

        static void DoSomething(Duck animal)
        {
            animal.MakeNoise();
        }
    }
}

Open in new window


vs.

namespace ConsoleCS
{
    using System;

    public interface IAnimal {
        void MakeNoise();
    }

    public class Duck : IAnimal
    {
        public void MakeNoise()
        {
            Console.WriteLine("quack.");
        }
    }

    public class Dog : IAnimal
    {
        public void MakeNoise()
        {
            Console.WriteLine("bark.");
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            DoSomething(new Dog());
            DoSomething(new Duck());
            Console.WriteLine("Done.");
            Console.ReadLine();
        }

        static void DoSomething(IAnimal animal)
        {
            animal.MakeNoise();
        }
    }
}

Open in new window


Interfaces allows to use different concrete types with the same methods. Thus reduced code.

And: when you change concrete types and have no interfaces, then it may happen that you change the signature (removing methods, changing parameters of existing methods). Thus the consumer now will no longer compile. In this case an interface is the contract between concrete type and consumer. During normal development cycles, you don't touch interfaces, thus your interaction stays save. Changing interfaces on the other hand is now an extra architectural step.
1
 
ste5anSenior DeveloperCommented:
And read Martin Fowler and Robert Martin..

Especially the SOLID principles.. they show the architectural aspects.
1
 
it_saigeDeveloperCommented:
One word of caution.  All interface members must be implemented!!!  If you need to have members that are not implemented by the child type, then you want to consider using a class instead of an interface (but you are only limited to inheriting from one class instance); e.g. -
public class Base { }

public class OtherBase { }

//This is invalid
public class Child : Base, OtherBase { } 

//These are valid
public class ChildOfBase : Base { } 
public class ChildOfOtherBase : OtherBase { }

Open in new window

You can mix interfaces with class inheritence; e.g. -
public class Base { }

public interface IOtherBase { }

public class Child : Base, IOtherBase { }

Open in new window

You are also not limited to the number of interfaces that you can implement; e.g. -
public class Base { }

public interface IOtherBase { }

public interface IUltimateBase { }

public class Child : Base, IOtherBase, IUltimateBase { }

Open in new window


So what does this mean?  Well extending upon what ste5an has already illustrated:
using System;
using System.Collections.Generic;

namespace EE_Q29068843
{
    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...");

            });
            Console.ReadLine();
        }
    }

    class Animal : IAnimal
    {
        public virtual string MakeNoise { get { return string.Empty; } }

        public string Name { get; set; }

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

    interface IAnimal
    {
        string Name { get; set; }
    }

    class Bear : Animal
    {
        public override string MakeNoise { get { return $"{ToString()} ROARS!!!"; } }
    }

    class Fish : Animal { }

    class Dog : Animal
    {
        public override string MakeNoise { get { return $"{ToString()} BARKS!!!"; } }
    }

    class Cat : Animal
    {
        public override string MakeNoise { get { return $"{ToString()} MEOWS!!!"; } }
    }
}

Open in new window

Which produces the following output -Capture.PNG
-saige-
0
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.