Which visibility modifier is more permissive: Protected or Internal?
internal var num = 18
protected set // throws an error at 'protected' showing: Setter visibility must be the same or less permissive than property visibility
And I try this also:
protected var num = 18
internal set // throws an error at 'internal' showing: Setter visibility must be the same or less permissive than property visibility
They aren't comparable; neither is more permissive than the other.
A subclass in another module will see protected members, but not internal.
An unrelated class in the same module will see internal members, but not protected.
protected means that the member has the same visibility as one marked as private, but that it is also visible in subclasses.
internal means that any client inside this module who sees the declaring class sees its internal members.
Related
Just when I thought I understood it, I got the following issue.
I have a base class in another module (called base here)
It looks like that:
open class BaseTest {
companion object {
lateinit var baseTest: BaseTest
}
protected open var someProperty: String? = "base"
}
I want to set that property and made it protected so my extended class in another module could access it.
class Extended: BaseTest() {
fun extendedCall() {
BaseTest().someProperty = "extended"
baseTest.someProperty = "extended"
}
}
However, neither the static one, not the direct property is accessable stating the following error:
Cannot access 'someProperty': it is protected in 'BaseTest'
But shouldn't that be accessable since Extended inherents from BaseTest()? I mean the definition of protected is "Declarations are only visible in its class and in its subclassess" so what have I missed? It even doesn't work in the same module so that's not the cause.
What am I missing?
BaseTest().someProperty = "extended"
Here you make a new BaseTest object by calling the constructor BaseTest() and you are not allowed to access protected properties of other BaseTest objects.
baseTest.someProperty = "extended"
the static BaseTest object is also another object and not the Extended object itself.
Being protected merely makes it possible to do
someProperty = "extended"
or the equivalent
this.someProperty = "extended"
That is, access the property of this object.
I believe the protected modifier doesn't work like that in Kotlin.
The documentation says:
The protected modifier is not available for top-level declarations.
But I agree it's quite confusing as written. It appears the documentation focuses more on the Outter/Inner class relationship via the this keyword.
I define an interface containing a trivial/simple property and an implementing class that sets the property in its constructor:
interface class IMyInterface
{
public:
property System::String^ MyName;
};
ref class MyImplementingClass : public IMyInterface
{
public:
virtual property System::String^ MyName;
MyImplementingClass()
{
MyName = "Test Name";
}
};
This doesn't seem too contentious, but when I run Code Analysis in Visual Studio 2019 using the default 'Microsoft Mixed (C++/CLR) Recommended Rules' ruleset it triggers warning CA2214:
warning CA2214: Microsoft.Usage : 'MyImplementingClass::MyImplementingClass(void)' contains a call chain that results in a call to a virtual method defined by the class. Review the following call stack for unintended consequences:
warning CA2214: MyImplementingClass..ctor()
warning CA2214: MyImplementingClass.set_MyName(String):Void
So I think it's complaining because setting this property involves calling the automatically implemented method set_MyName() and since that method is virtual it is considered a violation to call it from a constructor.
Does that mean this whole pattern is invalid?
What is the correct way to set the value of an inherited property at construction time?
On my sub class if I override the property, we call it property XYZ is overriding the property from the base class. What do you call if property is getting renewed by using new keyword? Renewed?
This using of the new keyword as modifier is called member hiding.
From MSDN Documentation:
When used as a declaration modifier, the new keyword explicitly hides a member that is inherited from a base class. When you hide an inherited member, the derived version of the member replaces the base class version. Although you can hide members without using the new modifier, you get a compiler warning. If you use new to explicitly hide a member, it suppresses this warning.
To hide an inherited member, declare it in the derived class by using the same member name, and modify it with the new keyword.
public class BaseC
{
public int x;
public void Invoke() { }
}
public class DerivedC : BaseC
{
new public void Invoke() { }
}
For more information when to use override and when to use new keyword modifier you can read in MSDN too.
In Swift, what is the conventional way to define the common pattern where a property is to be externally readonly, but modifiable internally by the class (and subclasses) that own it.
In Objective-C, there are the following options:
Declare the property as readonly in the interface and use a class extension to access the property internally. This is message-based access, hence it works nicely with KVO, atomicity, etc.
Declare the property as readonly in the interface, but access the backing ivar internally. As the default access for an ivar is protected, this works nicely in a class hierarchy, where subclasses will also be able to modify the value, but the field is otherwise readonly.
In Java the convention is:
Declare a protected field, and implement a public, read-only getter (method).
What is the idiom for Swift?
Given a class property, you can specify a different access level by prefixing the property declaration with the access modifier followed by get or set between parenthesis. For example, a class property with a public getter and a private setter will be declared as:
private(set) public var readonlyProperty: Int
Suggested reading: Getters and Setters
Martin's considerations about accessibility level are still valid - i.e. there's no protected modifier, internal restricts access to the module only, private to the current file only, and public with no restrictions.
Swift 3 notes
2 new access modifiers, fileprivate and open have been added to the language, while private and public have been slightly modified:
open applies to class and class members only: it's used to allow a class to be subclassed or a member to be overridden outside of the module where they are defined. public instead makes the class or the member publicly accessible, but not inheritable or overridable
private now makes a member visible and accessible from the enclosing declaration only, whereas fileprivate to the entire file where it is contained
More details here.
As per #Antonio, we can use a single property to access as the readOnly property value publicly and readWrite privately. Below is my illustration:
class MyClass {
private(set) public var publicReadOnly: Int = 10
//as below, we can modify the value within same class which is private access
func increment() {
publicReadOnly += 1
}
func decrement() {
publicReadOnly -= 1
}
}
let object = MyClass()
print("Initial valule: \(object.publicReadOnly)")
//For below line we get the compile error saying : "Left side of mutating operator isn't mutable: 'publicReadOnly' setter is inaccessible"
//object.publicReadOnly += 1
object.increment()
print("After increment method call: \(object.publicReadOnly)")
object.decrement()
print("After decrement method call: \(object.publicReadOnly)")
And here is the output:
Initial valule: 10
After increment method call: 11
After decrement method call: 10
I've got a producer method that wants to produce a set that is unmodifiable:
// EnumSet.noneof returns an object of type Serializable, and also
// Collections#synchronizedSet javadoc says, "The returned set will be
// serializable if the specified set is serializable."
private final Set<Role> roles =
Collections.synchronizedSet(EnumSet.noneOf(Role.class));
...
#Produces #LoggedIn public Set<Role> getRoles()
{
// Collections#unmodifiableSet javadoc also says, "The returned set will be
// serializable if the specified set is serializable."
return Collections.unmodifiableSet(this.roles);
}
I want to inject the set into a session scoped bean:
#Inject #LoggedIn Set<Role> roles;
At the injection point a warning is issued, saying that I cannot inject a set, which is not serializable, into a bean of passivating scope. The warning makes sense because the Set interfaces does not extend Serializable. However, in this circumstance it would appear, according to the javadoc, that roles is in fact serializable. I am not sure of the best way to handle this situation in order to avoid the warning.
Incidentally, I've noticed that applying #SuppressWarnings({"NonSerializableFieldInSerializableClass"}) at the injection point does not suppress the warning. But what I've also noticed that the following line of code in the same session scoped bean, located right next to the injection point, does NOT cause a warning message to be issued:
#Inject #LoggedIn Set<Role> roles; // warning
private Set<Role> roles1; // no warning!
Weird!
I have three questions:
What would be the best approach to take in this circumstance?
Why does #Inject #LoggedIn Set<Role> roles cause a warning whereas private Set<Role> roles1 does not?
Why does applying #SuppressWarnings({"NonSerializableFieldInSerializableClass"}) at the injection point not suppress the warning?
Only the first line is an injection point, hence CDI will scan it and ensure that it can be injected. The second line is not scanned by CDI to ensure that it's injectable, because CDI isn't trying to inject into it.
SuppressWarnings is a compile time annotation, not a runtime. It's lost in the compiled class.
You can create a Set implementation that implements serializable and use that. It should be injected as that set impl.