LSP applies to passing an instance of a class into a method, having the method do some stuff with that instance, and often produce some sort of result. This doesn't matter for static classes since in C# you cannot create an instance of a static class.
Even more importantly, static classes are sealed and therefore cannot be inherited. This makes your question moot far as C# goes.
You could say that static classes are always LSP-compliant since you cannot ever produce a subclass that would violate that principle. You could also say that static classes are never LSP-compliant for the same reason.
In Java, static classes are slightly different. You cannot mark a top-level class as "static", so if you want to create a utility class similar to C#'s static classes you have to declare it as
final
and hide its constructor. Once you do that, though, they behave similarly to C# - you cannot instantiate them or subclass them. You can declare an inner class as
static
, but that does not mean the same thing as it does in C#: it simply denotes a
nested top-level class.
VB.NET behaves exactly the same way as C# in this case, far as I know.
You didn't mention whether you're interested in the other principles, but I'm going to include them anyway for completeness.
Single responsibility principle: a static class easily follow this principle.
Open/closed principle: since static classes are sealed, they cannot ever follow this principle.
Liskov substitution principle: as above.
Interface segregation principle: doesn't apply to a single class, but splitting one large static class into smaller, more specialized ones could be a step towards following this principle.
Dependency inversion principle: static classes cannot implement interfaces, so any class using it will always depend on whatever implementation exists at the time. Static classes therefore violate this principle.
Since static classes do not satisfy all 5 criteria, they are not SOLID.
First of all, the examples will be in C#. But I think you'll have no problem understanding it. So...
You CANNOT instantiate objects of an abstract class. You must have a subclass that derives from the class, if you want to instantiate it. But this probably won't help you since you may have come across that before.
So let's try an example.
Suppose you want to lose weight and your nutritionist asks you to track your food intake. When you go to her again, you can't tell her that you ate a "food". Although it's not wrong, since all food has calories, it is too "abstract" for her. So you need to tell her WHICH food.
So, if she were to code that... She'd have an abstract class Food.
abstract class Food
{
public int CaloriesPerPound { get; set; }
//...
}
Why? Because that wouldn't allow you to say "I ate a food".
{
Food fries = new Food(); //This won't even compile
}
So you need concrete classes:
class Fruit : Food
{
//Other stuff related only to fruits
}
class Bread : Food
{
//Other stuff related only to Bread
}
So you'll have to tell exactly which food it is.
{
Apple desert = new Apple(); //Now we are talking
}
But she still needs the food class, it is still interesting to her:
class Meal
{
public List<Food> Foods { get; set; }
//Other meal related stuff
public int TotalCalories()
{
int calories = 0;
foreach (Food food in Foods)
{
calories = calories + food.CaloriesPerPound * FoodQuantity;
}
return calories;
}
}
That's an example of when you need an abstract class. When you want to have a base class, but you don't want anyone creating an object of your class.
An abstract CAN have abstract methods. It doesn't need to. Is totally ok to have an abstract class without abstract methods. Speaking of which...
Abstract method is something that it's too broad. There's no similarities on how things work, so the classes that derive from your class that has an abstract method won't be able to call the super class implementation. And you're also forcing all the sub classes to implement their version of that method.
Let's try another example? An Animal Band Simulator. You'd have animals, and each one of them would make a sound. But those are very different "implementations", they have nothing in common A dog differs from a cat, a cat from an elephant, an elephant from a cricket. So you'd have an abstract method MakeSound.
class Animal
{
public abstract void MakeSound();
}
But, if you have an abstract method in your class, that makes the whole class abstract!
abstract class Animal
{
public abstract void MakeSound();
}
So the rest of the code might be:
class Dog : Animal
{
public void MakeSound()
{
//bark at the moon
}
}
class Cat : Animal
{
public void MakeSound()
{
//meowing for food
}
}
And the BAND!
class AnimalBand
{
public List<Animal> Animals { get; set; }
public void RockOn()
{
foreach (Animal animal in Animals)
{
animal.MakeSound();
}
}
}
So this is an example of when you use an abstract method.
I guess this is the essence. It may be a little forced/convoluted, but I think it gets the point across. Go back to the examples that didn't help you before and see if they make sense now.
I'm go out on a limb and say you're a beginner. This stuff may seem strange to you, and you may not see any benefit in using abstract classes.
It's ok. It's strange for almost all of us when we start. But in time, you'll learn to appreciate it.
Best Answer
Performance is not even the biggest problem here, secret dependencies and lying APIs are.
From a testable point of view, static methods are awful, because they usually represent global state, which, surprisingly, is awful as well, because it means if you run a function two times, you can get different results even when the inputs are the same (that is what global state does). How do you test that?
I cannot really see any case, where I would prefer static methods instead of normal ones. If you can, do not use them, if you must use them, your design is most likely wrong and needs refactoring.
Check Clean Code Talks by Miško Hevery from 2008, they are still relevant and provide great explanations on why static methods and singletons should be avoided.
Some youtube references to some talks by Miško Hevery: