Reputation: 4485
For a group of classes that all implement the same interface, say one or more have additional methods that are not part of the interface definition. When i create those objects, using the interface is there a way to access those methods? or do I have to create each individual object without using the interface?
class Program
{
static void Main(string[] args)
{
ITextProcessor processor = new FileProcessor();
string result = processor.ReadText();
processor.SaveText(result);
ITextProcessor processorTest = new FileProcessorTest();
processorTest.testMethod() // unavailable
}
}
class FileProcessor : ITextProcessor
{
public string ReadText()
{
// read in text from a
// file and return it
return Console.ReadLine();
}
public void SaveText(string processedText)
{
// write processedText out to file.
Console.WriteLine(processedText);
}
}
class FileProcessorTest : ITextProcessor
{
public string ReadText()
{
// read in text from a
// file and return it
return Console.ReadLine();
}
public void SaveText(string processedText)
{
// write processedText out to file.
Console.WriteLine(processedText);
}
public void testMethod()
{
//I want to be able to access this method
}
}
interface ITextProcessor
{
string ReadText();
void SaveText(string processedText);
}
Upvotes: 3
Views: 284
Reputation: 13765
You can't using an Interface in order to invoke another method that's not defined in the interface as this will broke the L
of SOLID principles
which state that
objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program
But as stated in other answer you can cast interface variable to the object but this is not recommended especially when you have many types of object inherits from the some interface
Upvotes: 1
Reputation: 25221
You can't - the whole point of using an interface is that you know that every implementer has every method, which you can't possibly know unless it's declared by the interface.
You could get around it by trying to cast to one of the concrete implementations and call the method if successful; however, this also defeats the point as interfaces are supposed to abstract these concrete implementations away from the classes using them (and this would not be "still programming to interfaces").
Consider this: If the class making use of the interface needs to use it for something that is not declared in the interface, is the interface being used the right one?
One thing you might consider is that perhaps your calling class needs more than just this interface. Maybe it needs one of these instead:
public interface ITestableTextProcessor : ITextProcessor
{
void TestMethod();
}
public class FileProcessorTest : ITestableTextProcessor {...}
Of course, whether this is appropriate (or even feasible) depends on what you're doing with it.
Upvotes: 4
Reputation: 8888
You can't do this. The interface is there as a "promise" that the classes implementing it will provide all of the declared methods. If you are going to add members willy-nilly to the derived classes, then that is NOT part of the interface - it's something specific to that specific class.
As such, you must cast the object as that particular class if you want to use the extra method.
If you declare it as an interface, then you will only ever get access to methods in the interface - the extra ones will be hidden until you cast.
In other words:
class Program
{
static void Main(string[] args)
{
ITextProcessor processor = new FileProcessor();
string result = processor.ReadText();
processor.SaveText(result);
ITextProcessor processorTest = new FileProcessorTest();
// cast processorTest as the specific type to access the extra method
((FileProcessorTest)processorTest).testMethod()
}
}
Upvotes: 1
Reputation: 4727
You could try this:
class Program
{
static void Main(string[] args)
{
ITextProcessor processor = new FileProcessor();
string result = processor.ReadText();
processor.SaveText(result);
ITextProcessor processorTest = new FileProcessorTest();
if (processorTest is FileProcessorTest)
{
((FileProcessorTest)processor).testMethod();
}
}
}
If you don't want to do this check or know in code what instance you have, then maybe it's easier to directly assign the type of the class:
FileProcessorTest processorTest = new FileProcessorTest();
processorTest.testMethod();
Upvotes: 1
Reputation: 3874
Yes, it's possible, but not desiderable:
ITextProcessor processor = new FileProcessorTest();
//what if you have multiple implementations of ITextProcessor with custom methods each?
if (processor is FileProcessorTest) {
((FileProcessorTest)processor).testMethod();
}
Upvotes: 1