The main difference is the compiler won't let you instantiate an abstract class, while you could instantiate a base class (which may not make sense).
AbstractType a = new AbstractType(); //compiler error
AbstractType d = new DerivedType(); //OK
BaseType b = new BaseType(); //OK
Notice with the variable d
we are guaranteed that the abstract methods have been overridden (otherwise the DerivedType
class would have a compiler error).
Since you are commenting a lot of confusion still I'll give you the example I had that really made this concept click for me. Imagine you are making a tower defense game. You have a tower class, and every tower has the ability to attack, so you make an abstract tower class like this:
abstract class Tower
{
abstract void Attack();
}
Now I can make several tower classes:
class FlameTower : Tower
{
override void Attack()
{
//Shoot flames at everyone
}
}
class IceTower : Tower
{
override void Attack()
{
//Shoot ice everywhere
}
}
Now if you want to declare a list of towers, you can write:
List<Tower> towerList = new List<Tower>();
towerList.Add(new FireTower());
towerList.Add(new IceTower());
then iterate through them and make them all attack:
foreach (Tower t in towerList)
{
t.Attack();
}
And every class is guaranteed to have implemented attack because it was marked abstract and would be a compile error if they did not. Now all this could be done with a base class, except a base class would allow this:
towerList.Add(new Tower());
Now when it tries to call attack on that new Tower()
it's going to hit a blank abstract method, which is not what we want. So to forbid declaring something as a generic tower, we make the class abstract, then we know everything will have it's own definition of Attack
and it will do something.