考虑以下课程:
public class Vehicle { ... }
public class Coverage { ... }
public class VehicleList : IEnumerable<Vehicle> { ... }
public class CoverageList : IEnumerable<Coverage> { ... }
public abstract class Quote
{
protected VehicleList vehicles;
protected CoverageList coverages;
internal Quote() { ... }
public IReadOnlyCollection<Vehicle> Vehicles
{
get { return this.vehicles.AsReadOnly(); }
}
public IReadOnlyCollection<Coverage> Coverages
{
get { return this.coverages.AsReadOnly(); }
}
...
}
public sealed class OhQuote : Quote
{
//needs to access protected fields
...
}
public sealed class InQuote : Quote { ... }
public sealed class MiQuote : Quote { ... }
Quote
完全封装了VehicleList
和CoverageList
的功能,因此我想将这些类标记为internal
。问题是它们是protected
类的public
字段的类型。如果我将这些字段标记为protected internal
,则它们为protected
或internal
。我真正需要的是protected
和internal
(protected
在集会中优先)。您可以看到Quote
(具有internal
构造函数)及其子类(sealed
)都不能扩展到程序集之外。我已经想出如何使用公共接口实现所需的功能,但是想确保没有更简洁的方法。
答案 0 :(得分:5)
虽然.NET运行时支持这个概念(&#34; FamilyAndAssembly&#34;),但C#目前没有。
这是以private protected访问修饰符的形式为C#6.0提出的,但该功能已被删除。
更新: private protected
已添加到C# 7.2。
答案 1 :(得分:1)
作为附录: 如果您不想使用接口,并且您看到 - 没有C#支持来实现该目标,记住:您始终可以使用 反射 做那种非常奇怪和奇怪的事情。
您可以将字段设置为private
并使用反射,您可以从任何位置分配新值,当然也可以从同一程序集中的派生类中分配。
答案 2 :(得分:1)
我质疑派生类是否需要直接访问$('.admin_popup').on('click',function(){
$(".light_admin,.white_overlay").slideDown("slow", function(){
$(".admin_help_popup").animate({"min-height": "380px"}, "fast");
});
});
$('.close_admin_popup').on('click',function(){
$(".admin_help_popup").css("min-height", "0px");
$(".light_admin,.white_overlay").slideUp("slow");
});
的字段。
我在询问是否有办法在不使用公共接口的情况下实现所需的功能。
我认为您可以安全地将字段上的修饰符更改为Quote
,并让派生类通过private
中定义的protected
方法操作字段间接基类。不需要额外的公共接口。
以下是它的外观示例:
Quote
此替代方案实现了间接将public class Vehicle {}
public class Coverage {}
// Set these as "internal" as you were hoping for...
internal class VehicleList : IEnumerable<Vehicle>
{
public void Foo() {}
}
internal class CoverageList : IEnumerable<Coverage>
{
public void Bar() {}
}
public abstract class Quote
{
// Mark these as "private"
private VehicleList vehicles;
private CoverageList coverages;
internal Quote() {}
public IReadOnlyCollection<Vehicle> Vehicles
{
get { return this.vehicles.AsReadOnly(); }
}
public IReadOnlyCollection<Coverage> Coverages
{
get { return this.coverages.AsReadOnly(); }
}
// Add protected methods to manipulate the private fields.
protected void PerformFooOnVehicles()
{
this.vehicles.Foo();
}
protected void PerformBarOnCoverages()
{
this.coverages.Bar();
}
}
public sealed class OhQuote : Quote
{
// We now have indirect access to Quote's private fields.
public void Baz()
{
this.PerformBarOnCoverages();
this.PerformFooOnVehicles();
}
}
public sealed class InQuote : Quote {}
public sealed class MiQuote : Quote {}
和VehicleList
仅暴露给属于同一程序集的派生类的目标。