Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Many of the most popular programming languges (such as C++, Java, Python etc.) have the concept of hiding / shadowing of variables or functions. When I've encountered hiding or shadowing they have been the cause of hard to find bugs and I've never seen a case where I found it necessary to use these features of the languages.

To me it would seem better to disallow hiding and shadowing.

Does anybody know of a good use of these concepts?

Update:
I'm not refering to encapsulation of class members (private/protected members).

share|improve this question
    
That's why all my fieldnames start with F. –  Pieter B Oct 21 '13 at 12:24
7  
I think Eric Lippert had a nice article on this. Oh wait, here it is: blogs.msdn.com/b/ericlippert/archive/2008/05/21/… –  Lescai Ionel Oct 21 '13 at 13:14
1  
Please clarify your question. Are you asking about information hiding in general, or about the specific case described in the Lippert article where a derived class hides functions of the base class? –  Aaron Kurtzhals Oct 21 '13 at 16:46

6 Answers 6

If you disallow hiding and shadowing, what you have is a language in which all variables are global.

That's clearly worse than allowing local variables or functions that may hide global variables or functions.

If you disallow hiding and shadowing, AND you attempt to "protect" certain global variables, you create a situation where the compiler tells the programmer "I'm sorry, Dave, but you can't use that name, it is already in use." Experience with COBOL shows that programmers almost immediately resort to profanity in this situation.

The fundamental issue is not hiding/shadowing, but global variables.

share|improve this answer
15  
Another disadvantage of forbidding shadowing is that adding a global variable might break the code because the variable had already been used in a local block. –  Giorgio Oct 21 '13 at 13:54
12  
"If you disallow hiding and shadowing, what you have is a language in which all variables are global." -- not necessarily: you can have scoped variables without shadowing, and you explained it. –  Thiago Silva Oct 21 '13 at 17:04
    
@ThiagoSilva: And then your language has to have a way to tell the compiler that this module IS allowed to access that module's "frammis" variable. Do you allow someone to hide/shadow an object he doesn't even know exists, or do you tell him about it to tell him why he's not allowed to use that name? –  John R. Strohm Oct 21 '13 at 19:17
    
-1 I hate downvoting, but this isn't answering the question. The OP is asking about why a child class is allowed to hide members of a parent class. Doesn't have anything to do with global variables. –  Phil Oct 21 '13 at 22:22
7  
@Phil, excuse me for disagreeing with you, but the OP asked about "hiding / shadowing of variables or functions", and the words "parent", "child", "class", and "member" appear nowhere in his question. That would seem to make it a general question about name scope. –  John R. Strohm Oct 21 '13 at 22:35

Does anybody know of a good use of these concepts?

Using accurate, descriptive identifiers is always a good use.

I could argue that variable hiding doesn't cause many bugs since having two very similarly named variables of the same/similar types (what you'd do if variable hiding was disallowed) is likely to cause just as many bugs and/or just as severe bugs. I don't know if that argument is correct, but it's at least plausibly debatable.

Using some kind of hungarian notation to differentiate fields vs local variables gets around this, but has its own impact on maintenance (and programmer sanity).

And (perhaps most likely the reason that the concept is known of in the first place) it's far easier for languages to implement hiding/shadowing than to disallow it. Easier implementation means that compilers are less likely to have bugs. Easier implementation means that the compilers take less time to write, causing earlier and broader platform adoption.

share|improve this answer
3  
Actually, no, it is NOT easier to implement hiding and shadowing. It is actually easier to implement "all variables are global". You only need one namespace, and you ALWAYS export the name, as opposed to having multiple namespaces and having to decide for each name whether to export it. –  John R. Strohm Oct 21 '13 at 15:42
5  
@JohnR.Strohm - Sure, but as soon as you have any sort of scoping (read: classes) then having the scopes hide lower scopes is there for free. –  Telastyn Oct 21 '13 at 15:57
    
Scoping and classes are different things. With the exception of BASIC, every language I've programmed in has scoping, but not all of them have any concept of classes or objects. –  Michael Shaw Oct 21 '13 at 21:28
    
@michaelshaw - of course, I should have been more clear. –  Telastyn Oct 21 '13 at 22:37

Just to ensure we're on the same page, method "hiding" is when a derived class defines a member of the same name as one in the base class (which, if it is a method/property, is not marked virtual/overridable), and when invoked from an instance of the derived class in "derived context", the derived member is used, while if invoked by the same instance in the context of its base class, the base class member is used. This is different from member abstraction/overriding where the base class member expects the derived class to define a replacement, and from scope/visibility modifiers that "hide" a member from consumers outside the desired scope.

The short answer to why it's allowed is that not to do so would force developers to violate several key tenets of object-oriented design.

Here's the longer answer; first, consider the following class structure in an alternate universe where C# doesn't allow member hiding:

public interface IFoo
{
   string MyFooString {get;}
   int FooMethod();
}

public class Foo:IFoo
{
   public string MyFooString {get{return "Foo";}}
   public int FooMethod() {//incredibly useful code here};
}

public class Bar:Foo
{
   //public new string MyFooString {get{return "Bar";}}
}

We want to uncomment the member in Bar, and by so doing, allow Bar to provide a different MyFooString. However, we cannot do so because it would violate out alternate-reality prohibition on member hiding. This particular example would be rife for bugs and is a prime example of why you might want to ban it; for instance, what console output would you get if you did the following?

Bar myBar = new Bar();
Foo myFoo = myBar;
IFoo myIFoo = myFoo;

Console.WriteLine(myFoo.MyFooString);
Console.WriteLine(myBar.MyFooString);
Console.WriteLine(myIFoo.MyFooString);

Off the top of my head, I'm actually not sure whether you'd get "Foo" or "Bar" on that last line. You'd definitely get "Foo" for the first line and "Bar" for the second, even though all three variables reference exactly the same instance with exactly the same state.

So, the language's designers, in our alternate universe, discourage this obviously bad code by preventing property hiding. Now, you as the coder have a genuine need to do exactly this. How do you get around the limitation? Well, one way is to name Bar's property differently:

public class Bar:Foo
{
   public string MyBarString {get{return "Bar";}}       
}

Perfectly legal, but it's not the behavior we want. An instance of Bar will always produce "Foo" for the property MyFooString, when we wanted it to produce "Bar". Not only do we have to know that our IFoo is specifically a Bar, we also have to know to use the different accessor.

We could also, quite plausibly, forget the parent-child relationship and implement the interface directly:

public class Bar:IFoo
{
   public string MyFooString {get{return "Bar";}}
   public int FooMethod() {...}
}

For this simple example it's a perfect answer, as long as you only care that Foo and Bar are both IFoos. The usage code a couple examples up would fail to compile because a Bar isn't a Foo and can't be assigned as such. However, if Foo had some useful method "FooMethod" that Bar needed, now you can't inherit that method; you'd either have to clone its code in Bar, or get creative:

public class Bar:IFoo
{
   public string MyFooString {get{return "Bar";}}
   private readonly theFoo = new Foo();

   public int FooMethod(){return theFoo.FooMethod();}
}

This is an obvious hack, and while some implementations of O-O language specs amount to little more than this, conceptually it's wrong; if consumers of Bar need to expose Foo's functionality, Bar should be a Foo, not have a Foo.

Obviously, if we controlled Foo, we can make it virtual, then override it. This is the conceptual best practice in our current universe when a member is expected to be overridden, and would hold in any alternate universe that didn't allow hiding:

public class Foo:IFoo
{
   public virtual string MyFooString {get{return "Foo";}}
   //...
}

public class Bar:Foo
{
   public override string MyFooString {get{return "Bar";}}
}

The problem with this is that virtual member access is, under the hood, relatively more expensive to perform, and so you typically only want to do it when you need to. The lack of hiding, however, forces you to be pessimistic about the members which another coder that doesn't control your source code might want to reimplement; the "best practice" for any non-sealed class would be to make everything virtual unless you specifically didn't want it to be. It also still doesn't give you the exact behavior of hiding; the string will always be "Bar" if the instance is a Bar. Sometimes it is genuinely useful to leverage the layers of hidden state data, based on the level of inheritance at which you're working.

In summary, allowing member hiding is the lesser of these evils. Not having it would generally lead to worse atrocities committed against object-oriented principles than allowing it does.

share|improve this answer
    
+1 for addressing the actual question. A good example of a real-world usage of member hiding is the IEnumerable and IEnumerable<T> interface, described in Eric Libbert's blog post on the topic. –  Phil Oct 21 '13 at 22:05
    
Overriding is not hiding. I don't agree with @Phil that this addresses the question. –  Jan Hudec Oct 22 '13 at 10:56
    
My point was that overriding would be a substitute for hiding when hiding is not an option. I agree, it's not hiding, and I say as much in the very first paragraph. None of the workarounds to my alternate-reality scenario of no hiding in C# are hiding; that's the point. –  KeithS Oct 22 '13 at 14:23
    
I don't like your uses of shadowing/hiding. The main good uses I see are (1) kludging around the situation where a new version of a base class includes a member which conflicts with consumer code designed around an older version [ugly but necessary]; (2) faking things like return-type covariance; (3) dealing with cases where a base-class method is callable on a particular subtype but not useful. The LSP requires the former, but doesn't require the latter if the base-class contract specifies that some methods may not be useful in some conditions. –  supercat Jan 28 at 22:03

Your question could be read two ways: either you're asking about variable/function scope in general, or you're asking a more specific question about scope in an inheritance hierarchy. You didn't mention inheritance specifically, but you did mention hard to find bugs, which sounds more like scope in the context of inheritance than plain scope, so I'll answer both questions.

Scope in general is a good idea, because it allows us to focus our attention on one specific (hopefully small) portion of the program. Because it lets local names always win, if you read only the portion of the program that's in a given scope, then you know exactly what parts were defined locally and what was defined elsewhere. Either the name refers to something local, in which case the code that defines it is right in front of you, or it's a reference to something outside the local scope. If there aren't any non-local references that could change out from under us (especially global variables, which could be changed from anywhere), then we can evaluate whether the part of the program in the local scope is correct or not without referring to any part of the rest of the program at all.

It may possibly occasionally lead to a few bugs, but it more than compensates by preventing an enormous amount of otherwise possible bugs. Other than making a local definition with the same name as a library function (don't do that), I can't see an easy way to introduce bugs with local scope, but local scope is what lets many parts of the same program use i as the index counter for a loop without clobbering each other, and lets Fred down the hall write a function that uses a string named str that won't clobber your string with the same name.

I found an interesting article by Bertrand Meyer that discusses overloading in the context of inheritance. He brings up an interesting distinction, between what he calls syntactic overloading (meaning that there are two different things with the same name) and semantic overloading (meaning that there are two different implementations of the same abstract idea). Semantic overloading would be fine, since you meant to implement it differently in the subclass; syntactic overloading would be the accidental name collision that caused a bug.

The difference between overloading in an inheritance situation which is intended and which is a bug is semantics (the meaning), so the compiler has no way of knowing whether what you did is right or wrong. In a plain scope situation, the right answer is always the local thing, so the compiler can figure out what the right thing is.

Bertrand Meyer's suggestion would be to use a language like Eiffel, which doesn't allow name clashes like this and forces the programmer to rename one or both, thus avoiding the problem entirely. My suggestion would be to avoid using inheritance entirely, also avoiding the problem entirely. If you can't or don't want to do either of those things, there are still things you can to to reduce the probability of having a problem with inheritance: follow the LSP (Liskov Substitution Principle), prefer composition over inheritance, keep your inheritance hierarchies shallow, and keep the classes in an inheritance hierarchy small. Also, some languages may be able to issue a warning, even if they wouldn't issue an error, as a language like Eiffel would.

share|improve this answer

Here are my two cents.

Programs can be structured into blocks (functions, procedures) that are self-contained units of program logic. Each block can refer to "things" (variables, functions, procedures) using names / identifiers. This mapping from names to things is called binding.

The names used by a block fall into three categories:

  1. Locally defined names, e.g. local variables, that are only known inside the block.
  2. Arguments that are bound to values when the block is invoked and can be used by the caller to specify input / output parameter of the block.
  3. External names / bindings that are defined in the environment in which the block is contained and are in scope within the block.

Consider for example the following C program

#include<stdio.h>

void print_double_int(int n)
{
  int d = n * 2;

  printf("%d\n", d);
}

int main(int argc, char *argv[])
{
  print_double_int(4);
}

The function print_double_int has a local name (local variable) d, and argument n, and uses the external, global name printf, which is in scope but not defined locally.

Notice that printf could also be passed as an argument:

#include<stdio.h>

void print_double_int(int n, int printf(const char *, ...))
{
  int d = n * 2;

  printf("%d\n", d);
}

int main(int argc, char *argv[])
{
  print_double_int(4, printf);
}

Normally, an argument is used to specify input / output parameters of a function (procedure, block), whereas global names are used to refer to things like library functions that "exist in the environment", and therefore it is more convenient to mention them only when they are needed. Using arguments instead of global names is the main idea of dependency injection, which is used when dependencies must be made explicit instead of being resolved by looking at the context.

Another similar use of externally defined names can be found in closures. In this case a name defined in the lexical context of a block can be used within the block, and the value bound to that name will (typically) continue to exist as long the block refers to it.

Take for example this Scala code:

object ClosureExample
{
  def createMultiplier(n: Int) = (m: Int) => m * n

  def main(args: Array[String])
  {
    val multiplier3 = createMultiplier(3)
    val multiplier5 = createMultiplier(5)

    // Prints 6.
    println(multiplier3(2))

    // Prints 10.
    println(multiplier5(2))
  }
}

The return value of the function createMultiplier is the closure (m: Int) => m * n, which contains the argument m and the external name n. The name n is resolved by looking at the context in which the closure is defined: the name is bound to the argument n of function createMultiplier. Notice that this binding is created when the closure is created, i.e. when createMultiplier is invoked. So the name n is bound to the actual value of an argument for a particular invocation of the function. Contrast this with the case of a library function like printf, which is resolved by the linker when the program's executable is built.

Summarizing, it can be useful to refer to external names inside a local block of code so that you

  • don't need / want to pass externally defined names explicitly as arguments, and
  • you can freeze bindings at runtime when a block is created, and then access it later when the block is invoked.

Shadowing comes in when you consider that in a block you are only interested in relevant names that are defined in the environment, e.g. in the printf function that you want to use. If by chance you want to use a local name (getc, putc, scanf, ...) that has already been used in the environment, you simple want to ignore (shadow) the global name. So, when thinking locally, you do not want to consider the whole (possibly very big) context.

In the other direction, when thinking globally, you want to ignore the internal details of the local contexts (encapsulation). Therefore you need shadowing, otherwise adding a global name could break every local block that was using that name already.

Bottom line, if you want a block of code to refer to externally defined bindings, you need shadowing to protect local names from global ones.

share|improve this answer

Honestly, Eric Lippert, the principle developer on the C# compiler team, explains it pretty well (thanks Lescai Ionel for the link). .NET's IEnumerable and IEnumerable<T> interfaces are good examples of when member hiding is useful.

In the early days of .NET, we didn't have generics. So the IEnumerable interface looked like this:

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

This interface is what allowed us to foreach over a collection of objects, however we had to cast all those objects in order to use them properly.

Then came generics. When we got generics, we also got a new interface:

public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

Now we don't have to cast objects while we're iterating through them! Woot! Now, if member hiding was not allowed, the interface would have to look something like this:

public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumeratorGeneric();
}

This would be kind of silly, because GetEnumerator() and GetEnumeratorGeneric() in both cases do pretty much exactly the same thing, but they have slightly different return values. They are so similar, in fact, that you pretty much always want to default to the generic form of GetEnumerator, unless you're working with legacy code that was written before generics were introduced into .NET.

Sometimes member hiding does allow more room for nasty code and difficult-to-find bugs. However sometimes it's useful, such as when you want to change a return type without breaking legacy code. That's just one of those decisions language designers have to make: Do we inconvenience the developers who legitimately need this feature and leave it out, or do we include this feature into the language and catch flak from those who are victims of its misuse?

share|improve this answer
    
While formally the IEnumerable<T>.GetEnumerator() hides the IEnumerable.GetEnumerator(), this is only because C# does not have covariant return types when overriding. Logically it is an override, fully in line with LSP. Hiding is when you have local variable map in function in file that does using namespace std (in C++). –  Jan Hudec Oct 22 '13 at 11:07

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.