I’m currently exploring C# and working with Playwright in .NET. While I grasp the overall concept of interfaces, I’m a bit puzzled about their real-world application.
In some Playwright samples, I encounter code that looks like this:
However, the official documentation illustrates it differently:
class WebAutomationDemo
{
public static async Task Main()
{
using var driver = await WebDriver.InitializeAsync();
await using var session = await driver.Chrome.StartAsync();
var webpage = await session.OpenPageAsync();
await webpage.NavigateAsync("https://www.example.com");
// additional logic...
}
}
What confuses me is the use of IWebDriver, IBrowserSession, etc. I thought interfaces were just used to define what methods classes should implement. Yet, it appears we are directly using the interface to call methods here. Can someone clarify how this works? Where exactly does the actual object come from if we’re only declaring types as interfaces?
Think of it like this - the interface variable is just a placeholder that holds a reference to the actual implementation. When you declare IWebDriver _driver, you’re not creating anything yet. The magic happens when WebDriver.InitializeAsync() runs and returns a real object (like ChromeWebDriver or EdgeWebDriver) that implements IWebDriver. Your variable points to this real object, but you interact with it through the interface’s methods. This is dependency inversion - it’s everywhere in .NET. The benefit? You can swap implementations easily. Switch from Chrome to Firefox driver without changing any code that uses the interface. The library creates the right concrete class based on your config or method calls.
You’re mixing up interface declarations with creating actual objects. When you write IWebDriver _driver, you’re just making a reference that can hold any object that implements IWebDriver. The real object comes from calling something like WebDriver.InitializeAsync() - that’s what returns an actual class (like ChromeDriver or FirefoxDriver) that implements the interface. Here’s how to think about it: the interface is just a blueprint. Somewhere in the Playwright library, there are real classes that implement these interfaces. When you call those async methods, they create and return these concrete objects. You just work with them through the interface, which is better for abstraction and testing since you’re not locked into specific implementations.
interfaces r like contracts dude. when u do IWebDriver _driver, ur not creatin an instance. the real class that implements IWebDriver gets returned from WebDriver.InitializeAsync(). so _driver has an actual object, but u access it via the interface. it keeps ur code flexible!