I am new to OOP and have some questions.
Why can't methods declared in an interface have modifiers(public,private etc).
In this code:
class Program
{
static void Main(string[] args)
{
X ob = new Y();
ob.add(4, 5);
Z ob1 = new Y();
ob1.mull(2, 3);
Console.Read();
}
}
public interface X
{
void add(int x, int y);
}
public interface Z
{
void mull(int x, int y);
}
class Y : X, Z
{
void X.add(int x, int y)//here we are not decalring it as public ,why?
{
Console.WriteLine("sum of X and y is " + (x + y));
}
void Z.mull(int x, int 开发者_如何学编程y)
{
Console.WriteLine("product of X and Y is" + (x * y));
}
}
Both methods don't require modifiers but when I don't use interface, like X.add()
above, I need to make the implementation public. Why?
An interface is a contract. It says "I can do these things." What's the point of someone handing you an instance of IInterface
wherein you can't use some of the methods in that contract because they've been marked not public?
This is the rationale for designing the language in this way. The specification for this is in §13.2 of the language specification:
All interface members implicitly have public access. It is a compile-time error for interface member declarations to include any modifiers. In particular, interfaces members cannot be declared with the modifiers
abstract
,public
,protected
,internal
,private,
virtual
,override
, orstatic
.
As for your code, that is an example of explicit interface implementation. It is most useful for when a class or struct implements two interfaces each with a member having the same signature. For example, both IEnumerable
and IEnumerable<T>
define a method GetEnumerator
accepting no parameters.
public interface IEnumerable {
IEnumerator GetEnumerator();
}
public interface IEnumerable<T> : IEnumerable {
IEnumerator<T> GetEnumerator();
}
Note that by the above definitions, any class that implements IEnumerable<T>
must also implement IEnumerable
. Keep in mind that the return type is not part of the signature and thus we have a conflict with IEnumerable.GetEnumerator
and IEnumerable<T>.GetEnumerator
. This is what explicit interface implementation is meant to solve:
class X<T> : IEnumerable<T> {
List<T> _list = new List<T>();
public IEnumerator<T> GetEnumerator() {
return _list.GetEnumerator();
}
IEnumerator GetEnumerator() {
return GetEnumerator(); // invokes IEnumerable<T>.GetEnumerator
}
}
Members that are explicit interface implementations are only visible through an instance of the interface. Thus:
X<int> x = new X<int>();
var e1 = x.GetEnumerator(); // invokes IEnumerable<int>.GetEnumerator
// IEnumerable.GetEnumerator is not visible
IEnumerable y = x;
var e2 = y.GetEnumerator(); // invokes IEnumerable.GetEnumerator
Thus, in your code
X ob = new Y();
ob.add(1, 2); // X.add is visible through interface
Y y = new Y();
y.add(1, 2); // compile-time error, X.add is not visible
Both methods don't require modifiers but when I don't use interface, like X.add() above, I need to make the implementation public. Why?
Okay, it's not clear exactly what you're asking here. Access modifiers are not allowed for explicit interface implementations. This is 13.4:
It is a compile-time error for an explicit interface member implementation to include access modifiers, and it is a compile-time error to include the modifiers
abstract
,virtual
,override
, orstatic
.
If a interface implementation is not marked as being an explicit interface implementation, then it must have the access modifier public
. This is 13.4.4 (Interface mapping):
Interface mapping for a class or struct
C
locates an implementation for each member of each interface specified in the base class list ofC
. The implementation of a particular interface memberI.M
, whereI
is the interface in which the memberM
is declared, is determined by examining each class or structS
, starting withC
and repeating for each successive base class ofC
, until a match is located
If
S
contains a declaration of an explicit interface member implementation that matchesI
andM
, then this member is the implementation ofI.M
Otherwise, if
S
contains a declaration of a non-static public member that matchesM
, then this member is the implementation ofI.M
.A compile-time error occurs if implementations cannot be located for all members of all interfaces specified in the base class list of
C
.
So, in short, the compiler first looks for an explicit interface implementation. If it can not find one then it looks for a non-static, public member with the same signature as the method M
being implemented. If it can not find one a compile-time error occurs. So the rules are this. To implement an interface member I.M
:
If you implement
I.M
explicitly then the syntax isreturn-type I.M(parameter-list)
Otherwise, the syntax is
public return-type M(parameter-list)
Thus, with
interface IAdd {
int Add(int x, int y)
}
We can implement explicitly:
class Explicit : IAdd {
int IAdd.Add(int x, int y) { return x + y; }
}
or not:
class NotExplicit : IAdd {
public int Add(int x, int y) { return x + y; }
}
The difference is then that Explicit.Add
is not visible unless instances of Explicit
are typed as IAdd
:
IAdd explicitInterface = new Explicit();
explicitInterface.Add(2, 2);
Explicit explicit = new Explicit();
explicit.Add(2, 2); // compile-time error
whereas
IAdd notExplicitInterface = new NotExplicit();
notExplicitInterface.Add(2, 2);
NotExplicit notExplicit = new NotExplicit();
notExplicit.Add(2, 2); // okay, NOT a compile-time error as above
Does that help?
Interface is like a contact. When a class implements certain interface you are guaranteed that the interface members exist in the class to. If it was possible to change visibility then it would not work.
You might want to have a look at these questions:
How will I know when to create an interface?
Why can’t I have protected interface members?
Because interface members are automatically public. You're defining a contract through an interface, and it wouldn't make any sense for the members not to be public, as you must implement them in your implementing class.
Straight from Microsoft: "Interface members are always public because the purpose of an interface is to enable other types to access a class or struct."
Since your two interfaces don't define methods with the same signature, you don't need explicit implementation. You could do the following:
public void add(int x, int y)
{
Console.WriteLine("sum of X and y is " + (x + y));
}
public void mull(int x, int y)
{
Console.WriteLine("product of X and Y is" + (x * y));
}
That's implicit implementation of an interface, and now it's easier to call those methods on an instance of your class. Just call myInstance.add(1, 2)
instead of having to cast myInstance
to be an instance of the interface X
.
I'm going to back up and explain the symptoms you are reporting rather than try to explain why the public modifier is unnecessary; the other answers have explained that adequately.
Probably the reason you are confused is that you are using explicit interface implementation. When you use explicit interface implementation, you need to cast the object instance to that interface type before you can call its methods.
If you remove the "X." from your X.Add implementation, you'll be able to "see" and use the interface without the explicit cast. This is "implicit" interface implementation. As long as you don't have any name collisions, or some reason to make the interface members slightly less visible to normal clients, you probably want to prefer implicit interface implementation.
Because functions,fields etc declared in Interface have always public modifier by default. So when implementing it you dont have to type public because class already now method is Interface implementation so its public. In classes all fields and methods are privete but deafult.
This is the difference between an Explict and Implict implementation of an interface.
You'll usually want to implement an interface implicitly, meaning that the implemented members are publically available. This makes sense when you consider that implementing an interface usually represents that a class can perform a given feature (such as being disposed via IDisposable).
In scenarios where you need a type to implement an interface but don't want those interface members to be publically accessible you use an explicit implemention. The members are still accessible, but only when referencing the type via the interface.
精彩评论