C# 覆盖但不覆盖';不打电话
您如何在C#中声明一个应该由一个被撤销的类重写(或可重写)的方法——甚至可能在您的程序集之外——但该方法应该只能从实际的类中调用 (如C++中的私有虚函数) [编辑]C# 覆盖但不覆盖';不打电话,c#,inheritance,virtual,access-modifiers,C#,Inheritance,Virtual,Access Modifiers,您如何在C#中声明一个应该由一个被撤销的类重写(或可重写)的方法——甚至可能在您的程序集之外——但该方法应该只能从实际的类中调用 (如C++中的私有虚函数) [编辑] privatevirtual正是我想要的:“这里有一种方法可以修改我的行为,但是你仍然不能直接调用这个函数(因为调用它需要神秘的调用,而只有我的基类才能这样做)” 所以要澄清一下:在C#中,什么是最好的表达方式?私有成员对子类不可见。我想受保护的虚拟机会按你喜欢的方式运行吗 更新: 这里更详细地解释了如何使用C#中的继承和重写函数
private
virtual
正是我想要的:“这里有一种方法可以修改我的行为,但是你仍然不能直接调用这个函数(因为调用它需要神秘的调用,而只有我的基类才能这样做)”
所以要澄清一下:在C#中,什么是最好的表达方式?私有成员对子类不可见。我想受保护的虚拟机会按你喜欢的方式运行吗 更新: 这里更详细地解释了如何使用C#中的继承和重写函数。我试图使用一个有意义的例子,但认为它理解它是一个糟糕的类设计,我永远不会建议实现以这种方式描述的类。然而,我希望这可能会给你一个途径,以一种可以接受的方式解决你最初的问题。没有办法阻止一个具体的类调用它的任何成员,但是如果你的结构是这样的,也许这不是问题
public abstract class Animal
{
public void DisplayAttributes()
{
Console.WriteLine(Header());
Console.WriteLine("Name: " + Name());
Console.WriteLine("Legs: " + Legs());
Console.WriteLine();
}
protected virtual int Legs()
{
return 4;
}
private string Header()
{
return "Displaying Animal Attributes";
}
protected abstract string Name();
}
public class Bird : Animal
{
protected override string Name()
{
return "Bird";
}
protected override int Legs()
{
return 2;
}
}
public class Zebra : Animal
{
protected override string Name()
{
return "Zebra";
}
}
public class Fish : Animal
{
protected override string Name()
{
return "Fish";
}
protected override int Legs()
{
return 0;
}
private string Header()
{
return "Displaying Fish Attributes";
}
protected virtual int Gils()
{
return 2;
}
public new void DisplayAttributes()
{
Console.WriteLine(Header());
Console.WriteLine("Name: " + Name());
Console.WriteLine("Gils: " + Gils());
Console.WriteLine();
}
}
class Program
{
static void Main(string[] args)
{
Bird bird = new Bird();
bird.DisplayAttributes();
//Displaying Animal Attributes
//Name: Bird
//Legs: 2
Zebra zebra = new Zebra();
zebra.DisplayAttributes();
//Displaying Animal Attributes
//Name: Zebra
//Legs: 4
Fish fish = new Fish();
fish.DisplayAttributes();
//Displaying Fish Attributes
//Name: Fish
//Gils: 2
List<Animal> animalCollection = new List<Animal>();
animalCollection.Add(bird);
animalCollection.Add(zebra);
animalCollection.Add(fish);
foreach (Animal animal in animalCollection)
{
animal.DisplayAttributes();
//Displaying Animal Attributes
//Name: Bird
//Legs: 2
//Displaying Animal Attributes
//Name: Zebra
//Legs: 4
//Displaying Animal Attributes
//Name: Fish
//Legs: 0
//*Note the difference here
//Inheritted member cannot override the
//base class functionality of a non-virtual member
}
}
}
公共抽象类动物
{
公共void displaytattributes()
{
Console.WriteLine(Header());
Console.WriteLine(“Name:+Name());
Console.WriteLine(“Legs:+Legs());
Console.WriteLine();
}
受保护的虚拟int Legs()
{
返回4;
}
私有字符串头()
{
返回“显示动物属性”;
}
受保护的抽象字符串名称();
}
公营鸟类:动物
{
受保护的重写字符串名称()
{
返回“鸟”;
}
受保护的覆盖int Legs()
{
返回2;
}
}
公共级斑马:动物
{
受保护的重写字符串名称()
{
返回“斑马”;
}
}
公营鱼类:动物
{
受保护的重写字符串名称()
{
归还“鱼”;
}
受保护的覆盖int Legs()
{
返回0;
}
私有字符串头()
{
返回“显示鱼属性”;
}
受保护的虚拟int Gils()
{
返回2;
}
公共新的void displaytattributes()
{
Console.WriteLine(Header());
Console.WriteLine(“Name:+Name());
Console.WriteLine(“Gils:+Gils());
Console.WriteLine();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
鸟=新鸟();
DisplayAttributes();
//显示动物属性
//姓名:伯德
//腿数:2
斑马=新斑马();
zebra.DisplayAttributes();
//显示动物属性
//姓名:斑马
//腿数:4
鱼=新鱼();
fish.DisplayAttributes();
//显示鱼类属性
//名称:鱼
//吉尔斯:2
List animalCollection=新列表();
动物采集。添加(鸟);
动物采集。添加(斑马);
动物采集。添加(鱼);
foreach(动物采集中的动物)
{
animal.DisplayAttributes();
//显示动物属性
//姓名:伯德
//腿数:2
//显示动物属性
//姓名:斑马
//腿数:4
//显示动物属性
//名称:鱼
//腿数:0
//*注意这里的区别
//继承的成员无法重写
//非虚拟成员的基类功能
}
}
}
在本例中,Bird、Zebra和Fish都可以调用它们的Name和Legs方法,但是在本例的上下文中,这样做不一定有用。此外,如Fish所示,可以针对具体派生类的实例修改DisplayAttributes();但是当你观察一个动物时,就像在foreach循环中一样,不管动物的实际类型是什么,你都会得到displaytattributes行为的基类。我希望这有助于提供您想要复制的功能类型。为什么您需要它是私有的?在这里,保护应该足够了。您要求子类作者编写他们无法调用的代码。这能实现什么?他们无论如何都可以使用该代码。当您说它应该只在“实际类”内可调用时,您是指基类还是派生类?这两种方法本身都不可行。最接近的方法是使用受保护的方法,这意味着可以从声明类、派生类和任何其他派生类调用该方法。在我阅读您的问题时,您可能有两个意思 首先,如果您希望类a中的函数可以在子类B中重写,但对任何外部类都不可见:
public class ClassA
{
protected virtual ReturnType FunctionName(...) { ... }
}
public class ClassB
{
protected override ReturnType FunctionName(...) { ... }
}
其次,如果要强制实现类定义函数:
public abstract class ClassA
{
protected abstract ReturnType FunctionName(...);
}
public class ClassB
{
protected override ReturnType FunctionName(...) { ... }
}
如果你只是深入研究C,你可能会看到另一个有点相关的概念,那就是分部类。这是在编译时合并两个源文件以创建一个类的想法,这两个类都来自同一个程序集:
文件1:
public partial class ClassA
{
private ReturnType FunctionName(...);
}
文件2:
public partial class ClassA
{
//actual implimentation
private ReturnType FunctionName(...){ ... };
}
除处理设计生成的文件(如Linq2Sql文件、EDM或WinForms等)外,Partials没有广泛使用。我想这不会像您预期的那样有效,但让我为您绘制一些伪代码:
public interface BaseClassFunction {
void PleaseCallMe();
}
public class BaseClass {
private BaseClassFunction fn;
public BaseClass(BaseClassFunction fn) {
this.fn = fn;
}
private CallMe() {
fn.PleaseCallMe();
}
public PublicCallMe() {
CallMe();
}
}
private class DerivedClassFunction : BaseClassFunction {
void PleaseCallMe() { ... do something important ... }
}
public class DerivedClassFunction {
public DerivedClassFunction() : BaseClass(new DerivedClassFunction()) {
}
}
C对“私有”的保证比C++强。在C++中,您确实可以重写私有虚拟方法。但这意味着基类中的代码可以执行派生类中的代码。打破了私有方法是真正私有的并且只能由同一类中的方法调用的承诺
<这里没有帮助的东西是C++没有。#include "stdafx.h"
#include <iostream>
class Base {
private:
virtual void Method() = 0;
public:
void Test() {
Method();
}
};
class Derived : public Base {
private:
void Method() { std::cout << "Who the heck called me?"; }
};
int _tmain(int argc, _TCHAR* argv[])
{
Base* p = new Derived;
p->Test();
}
public class Base
{
private Func<Base, int> func;
protected void SetFunc(Func<Base, int> func)
{
this.func = func;
}
private void CallFunc()
{
if (func != null)
{
var i = func(this);
}
}
}
public class Sub : Base
{
private void DoFuncyStuff()
{
this.SetFunc(b => 42);
}
}