Win a copy of Practice Tests for OCP Java 17 Certification Exam (1Z0-829) this week in the OCPJP forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Liutauras Vilda
Sheriffs:
  • Rob Spoor
  • Junilu Lacar
  • paul wheaton
Saloon Keepers:
  • Stephan van Hulst
  • Tim Moores
  • Tim Holloway
  • Carey Brown
  • Scott Selikoff
Bartenders:
  • Piet Souris
  • Jj Roberts
  • fred rosenberger

Protected accessor is wierd

 
Greenhorn
Posts: 25
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Say I have these two classes:


So I can call a protected method on a subclass in other package, however I cannot call it on the parent class Bird.

I think that is exactly the protected accessor rule, but is there a reason for that behavior? Seems wierd to me.
 
Saloon Keeper
Posts: 25608
183
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You are accessing a protected method on an object of type Bird. The fact that you are doing so within class Goose which inherits from Bird is immaterial, since you're not invoking the Goose's Bird super-method, you're invoking from outside the Bird.

If you changed "bird.makeNoise()" to "super.makeNoise()" that would compile, since then you'd be calling from within the Goose/Bird object. But that would not be the Bird object you just instantiated so it would not apply to the object you were targeting.
 
Marcelo Canaparro
Greenhorn
Posts: 25
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think I am a little lost on who needs access. Is it the class on which I am using an instance to call the protected method or is it the instance of the class I am calling the protected method?

Say I create another class:
 
Tim Holloway
Saloon Keeper
Posts: 25608
183
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You should not be able to invoke makeNoise() on either Bird or Goose instances from other classes such as class Main.

I say "should" because my Eclipse IDE is NOT flagging your latest code as invalid, and it SHOULD have. So I'm confused. It's acting like it sees protected as though it were package scope and that's wrong.
 
Marshal
Posts: 75836
361
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But Java®'s protected access always permits access in the same package; as I said yesterday, it is different from its C++ counterpart.
 
Marcelo Canaparro
Greenhorn
Posts: 25
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But protected allows for classes on the same package to call the variable or method just like the default acessor, but it also allows for subclasses to access it.

1 - If this permission is given to a subclass, no matter where I instantiate a new Goose instance, makeNoise should work.

2 - If that is not the case, and the instance class where I am instantiating a new Goose matters and must be on the same package or be also a subclass of Bird. It seems to me that making a new Bird inside Goose and calling makeNoise should work.
 
Tim Holloway
Saloon Keeper
Posts: 25608
183
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:But Java®'s protected access always permits access in the same package; as I said yesterday, it is different from its C++ counterpart.



You didn't say different how, though.

Now I see. Never ran into it, since I don't use protected as much in Java and always did so within strict inheritance. Curious that nobody ever mentioned that before (no, I don't read myself to sleep from the language specs).
 
Campbell Ritchie
Marshal
Posts: 75836
361
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:. . . You didn't say different how, though.. . .  nobody ever mentioned that before . . . .

Sorry.

I have come across other people who didn't realise there is that difference from C++. I know that the similarity in appearance helped Java®'s acceptance in its early days, but having a keyword with different meanings can cause confusion. It cuts both ways.

And I can never understand that section of the JLS.
 
Tim Holloway
Saloon Keeper
Posts: 25608
183
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Possibly the single most questionable decision that Gosling et. al. made when designing Java was to make package scope the default scope. Call me paranoid, but I'd much rather that the default scope be private.

The result here is that protected scope is an extension of package scope rather than directly from private scope. Having made the bad decision, this is somewhat logical, if not inevitable, but I'd rather not have had it done that way. And since it's a blratant quirk specific to Java, I'd have thought people would have written more about it. Humph. Package scope, incidentally, could be considered a variant of C++ "friend" scope, though the rules are very different.

I also haven't declared classes with any scope but public for æons. In fact, what little I knew about non-public classes is forgotten. The lessened need for inner classes with the addition of things like lambas didn't help on that, either.
 
Campbell Ritchie
Marshal
Posts: 75836
361
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There used to be a fifth access type private protected, which was probably the same as protected in C++, but that vanished very early, probably by JDK1.0.2. I suspect the importance of private access wan't as well understood back in 1996.
While we're on about things we don't like, what do you think about the absence of the undigned keyword? Apart from, “Campbell can't spell,” I mean.
 
Tim Holloway
Saloon Keeper
Posts: 25608
183
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If you're referring to the controversial lack of unsigned, I don't spend much time on the subject. Java is an abstract language and when I use it I think abstractly.

The really questionable part here is how Java supports bit and shift operations, since on the whole such things are really best done on unsigned entities anyway (arithmetic shifts notwithstanding)..

A certain sloppiness came over from C and other places. The concept of a (signed) byte. for example. Not all hardware originally considered a "byte" to be 8 bits. Depending on the CPU, it could be anywhere from about 6 bits up. ASCII characters were defined by the actual ASCII standard to be 7 bits, and the idea that a character and a byte are the same size is fallacious - Java being a prime example! Lumping all this stuff together under "things that can be converted directly to integers" (signed characters!) is really only forgivable in the sense that certain operations (notably dealing with external world interfaces like file contents and network packets) would be considerably more cumbersome if absolute datatype purity were enforced.

That's where the Ada language was superior. You could define cardinal numbers, ordinal numbers, and natural numbers as discrete non-mixable data types and you could use operator overloading for specific applications where the more forgiving syntax of languages like C would be convenient. Alas, Ada was too much for the machinery of its day. In 1990, a mid-sized IBM mainframe could compile Ada at roughly the same speed that my 4 MHz Z-80 could compile Fortran. Java is pretty demanding, but by then the hardware was more capable.

So, in short, I try to deal with sign-affected operations in Java with a great deal of caution and a lot of unit tests.
 
Marcelo Canaparro
Greenhorn
Posts: 25
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So I did some reasearch and found that:

protected allows for classes on the same package to call the variable or method, but it also allows for subclasses to access it only if using that subclass as reference

Am I correct?

Seems like a really arbitrary rule though.
 
Sheriff
Posts: 27224
87
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's not arbitrary, but it's not all that obvious why it isn't.

There needs to be a hierarchy of accessors, because there are Java language rules which require that. For example when you write an inherited method, you can declare it to have a different access than the superclass's method has. However you cannot declare it to have a wider access -- e.g. you can't override a private method by a public method. So you need a rule to compare two accessors and state which is "wider".

Now, if you didn't have packages in Java then this hierarchy would be public > protected > private. Simple. But there are packages and there's an accessor sometimes called "package private". It's denoted by being invisible, which is annoying but it's the reason why it's sometimes called "default" access. Anyway, it has to slot into that hierarchy somewhere. So that makes the hierarchy public > protected > (default) > private and that means that protected methods can access anything that (default) methods can, along with being able to access members from their superclasses.

The Java Language Specification states that rule much more precisely than I did there, but it uses phrases that aren't easy for a beginner to understand. However from the examples you posted I think you understand what can be done with "protected" and what can't. Am I right?
 
Tim Holloway
Saloon Keeper
Posts: 25608
183
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Technically there's no reason why package access has to be part of the hierarchy. It could have just as easily have been a distinct modifier external to the private -> protected -> public hierarchy and as Campbell has noted, a syntax could have provided for it.

I've mentioned the C++ "friend" qualifier. In C++ you can designate selected classes to be "friends" of a class and thereby have access to resources as though they were subclasses of that class even though they are entirely outside the class' inheritance structure. So package access is essentially just an implicit "friend" declaration for all classes within the same package.

In actual practice, I never found the C++ "friend" functionality to be that useful. Then again, the only time I find package-level access to be particularly desirable is when I'm pairing the primary package code with unit test code. I am, as I said, paranoid, so I prefer explicit relaxations to implicit ones.
 
Bartender
Posts: 1737
63
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
1. I've seen presentations where Stroustrop considered the whole friends with access benefits thing to have been a misstep, forever unfixable, in retrospect.
If he had a time machine he suggested he'd have gone back and slapped himself [someone else asked for it insistently and he gave in].
Whether that moment of realization came before or after Java designed their whole object model around packages being "Communes of Friends With Benefits" I am not sure...

2. Paul, I think you got this backwards in your quick post (post haste?):

There needs to be a hierarchy of accessors, because there are Java language rules which require that. For example when you write an inherited method, you can declare it to have a different access than the superclass's method has. However you cannot declare it to have a wider access -- e.g. you can't override a private method by a public method. So you need a rule to compare two accessors and state which is "wider".


When you override a method, you can ONLY make it more public or leave it the same.
This is why it is annoying that the abstract methods in the interfaces are IMPLICITLY public, you can easily forget the public modifier when implementing them.

In practice, I believe <default> methods can be overridden to protected or public, at your whim, and protected can be left protected or made public, as you see fit.

Your point still totally stands, but I think the backwards were detailed.

3. C#/.Net has proper separation of concerns in this regard.
You can have an access level that can be seen by:
everyone in the same package(assembly) and NOBODY ELSE: "internal" -- like Java's default that is never named

all subclasses, and NOBODY ELSE: "protected", in a strict sense

only subclasses that are in the same package(assembly) and no other subclasses, nor other classes in the package that aren't subclasses: "private protected"

any classes that are in the same package(assembly) and all sub-classes, regardless of packaging: "internal protected" which is similar to Java's "protected" which someone might actually want some time.

I have seen the most vitriolic and vituperative writings on the horrible harms of "protected" -- I suspect they were all thinking of Java's wild-and-crazy-guy approach.
On their own, the granting of access to one's sub-classes (child classes as many call them) or to the hippies living in your commune (default access in Java) should only be done with prudence and forethought, they warn.  Automatically tying the two together is a bridge too far for these people, when forced to write in Java, every single thing is either public or private in their code it seems.  In C#, maybe not quite as much.

Cheers!

I miss you guys...back to work.

 
Tim Holloway
Saloon Keeper
Posts: 25608
183
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The "friend" qualifier is so useless that I dropped it literally decades ago.

I developed the C++ for Amiga software development system that was marketed by Lattice/SAS and I think I may have used it there. I was re-creating the entire OS kernel API and more in object-oriented form, and it's possible that with the optimization levels in effect at the time it might have been beneficial, but I cannot recall any specific instances and it appears I have those files off-line so I can't check without retrieving them. All I can say is that I have no use for friend today and if it vanished from the language I wouldn't miss it..

Incindentally, back then, C++ didn't have namespaces, which would have probably changed some basic design decisions.

And I agree, protected isn't something that should be used too freely. Its main benefit is that you can use it to access partial services in the parent class without whatever side-effects the equivalent public function in the parent might provide unwanted. Then again, if you need that sort of thing, then probably your parent class itself needs an abstract parent class. Just because you can inherit doesn't mean that you should be overly-dependent on the internal structure of your ancestors!
 
Jesse Silverman
Bartender
Posts: 1737
63
Eclipse IDE Postgres Database C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Tim.  One thing I always remember about you is that you were the dude who did Lattice/SAS/C++ on the Amiga.
I was an Atari ST User, but I still remember that.

I used SAS/C exclusively for thousands of hours on the IBM Mainframe (both VM and MVS) for years, no C++ features...

I remember when they discontinued that and we switched to using the Unix port (also from SAS/C) on the mainframe -- definitely had some fun at that point.

Kinda remember them being related to Metacomco outside of the USA or maybe everywhere at some point.

The point is, friends are good, object-oriented programming is good, friend classes in OOPS are kinda questionable.

Making everything in a package or namespace automatically friendly, pretty questionable.  The friends have write benefits to your private parts....

O right, the reason I posted again is you reminded me of this quote from the tail end of the "Zen of Python", still available from "import this" at the Python prompt:



I have seen guidelines suggesting nesting namespaces is a very poor idea in C++, all of the C++ code I dealt with at my longest C++ job had oodles of deeply nested namespaces.

It was "not fun".

So maybe they meant "more honking great ideas" and maybe they meant "more namespaces"?? but not "more nested namespaces" -- that is honking but not great.
 
Tim Holloway
Saloon Keeper
Posts: 25608
183
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
MetaComCo. Now there's a name I haven't heard in years...

I never had the luxury of using C or C++ on the IBM mainframes. I lobbied for a C compiler heavily, but no luck. Then after I departed, they finally (some say because I departed) invested in one. Now. f course, Z-series processors have significant chunks of the C standard library running as native instructions.

Supposedly you can run gcc on a Project Hercules emulator - and in fact, I tried to help make that happen - but I've never actually gotten around to trying the finished product. Alas. We tried for years to get off Assembly Language for Systems-level programming - arcane macro sets, IBM's Pascal/VS compiler (which was a very good optimizing compiler), and more, but the only other programming language suitable for low-level systems-level work than assembler was IBM's PL/S. And that wasn't something they made available to customers.

The reason that you never saw SAS C++ on mainframes is simple. When Lattice approached me to take my product and sell it under their label, their real interest was to get C++ on OS/2, which they had staked a lot of their future on. They supplied me with the back-end data formats so that I could write a native C++ front-end. So far, so good. The Amiga product was based on using AT&T's translator product, but it was not going to run on a 16-bit segmented-model architecture. The AT&T program flow was just completely wrong for that. And besides, I would have loved to have had native compilation on the Amiga. It wouldn't be the first project I'd done for a 32-bit processor that could also run on 16 bits.

The klller was in the method overloading component. C++ was designed with a considerably more complex overloading mechanism that Java is. Or more probably, Java learned what not to do from C++. In C++ thanks to automatic conversion abilities, when presented with an overloaded method/function call, you had a scoring system and you were supposed to pick the method that had the best score. Problem was, it was entirely possible to get tied scores, and if there was a definitive way to break ties, I never learned it. And I didn't feel good about creating a product that might compile erratically or non-portably. So that killed that idea.

I don't think that SAS targeted the Atari ST, but compiling non-GUI apps on the Amiga required 1MB of RAM, GUI apps 1.5GB, and the only Atari size I know of was 512K. Actually, my A1000 came with only 256M, but everyone promptly installed another 256M in the front panet, and that was augmented by an external memory module. Later machines had internal slots and memory buses,
 
Campbell Ritchie
Marshal
Posts: 75836
361
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
For having a question mentioned in the January 2021 CodeRanch Journal, congratulations: this question earns you a cow
 
reply
    Bookmark Topic Watch Topic
  • New Topic