对接口还是不理解:看下面这段程序,希望回答问题的时候能按照我的问题一个一个的解答,万分感谢。如果有好的建议也请提出来,比如哪里能看到类似的书籍和举例。public class LPex
{
Cplex cplex=new Cplex(); internal static void methodA (IInterf1 face1, IInterf2[][] face2, IInterArray[][] ary)
{
double[] lb={1,2,3};
double[] ub={4,5,6};
IInterf2[] x= face1.GenerateArray(3, lb, ub):
ary[0] = new IInterArray[2]
ary[0][1]=face1.AddLe( something inside )
}
}这是CPLEX里一段典型的定义 优化方程 变量上下限的语句。让我看不明白的是:
1)方法的参数里有接口的引用还是实现了接口的类的引用。
2)引用这个接口能做什么
3)方法内部第三行程序,接口的引用face1,突然冒出个方法,GenerateArray,竟然又生成了个接口,这是在做什么?
4)第五行 也是, 一个接口的方法能生成另一个接口。这是什么意思?不是说接口的方法只能在类定义的时候才能实现么, 这里还没写就直接用它生成新的接口了, 而且通篇程序任何描述ary[0][1]内方法的语句。请前辈帮帮新人!!谢谢!!
{
Cplex cplex=new Cplex(); internal static void methodA (IInterf1 face1, IInterf2[][] face2, IInterArray[][] ary)
{
double[] lb={1,2,3};
double[] ub={4,5,6};
IInterf2[] x= face1.GenerateArray(3, lb, ub):
ary[0] = new IInterArray[2]
ary[0][1]=face1.AddLe( something inside )
}
}这是CPLEX里一段典型的定义 优化方程 变量上下限的语句。让我看不明白的是:
1)方法的参数里有接口的引用还是实现了接口的类的引用。
2)引用这个接口能做什么
3)方法内部第三行程序,接口的引用face1,突然冒出个方法,GenerateArray,竟然又生成了个接口,这是在做什么?
4)第五行 也是, 一个接口的方法能生成另一个接口。这是什么意思?不是说接口的方法只能在类定义的时候才能实现么, 这里还没写就直接用它生成新的接口了, 而且通篇程序任何描述ary[0][1]内方法的语句。请前辈帮帮新人!!谢谢!!
还是不明白,声明的是一个实现了该接口的类? 那个 face1 究竟是个类的引用还是 接口的引用,就口能有引用么?
在本程序里:face1 是 引用, 是个类的引用对么但是它实现了IInterf1, 如果 人 是object, 春哥就是个接口,相当于IInterf1,而face1是一个实现了春哥接口的某人的引用, 对么?
红色的是实例,即“狗粮”
谢谢您的耐心解释,您说得接口的实例, 是不是指一个实现了该接口的类的实例,因为接口不能实例化, 那这里是不是少写了sometype:IInterf1, 这类的声明呢?
我只想搞清楚传参数传进来的“internal static void methodA (IInterf1 face1, IInterf2[][] face2, IInterArray[][] ary)”IInterf1 face1,究竟是什么实例? 按你的说话,方法传进来的都是实例,而接口又不能实例化,那参数里接口类型的实例是什么概念呢?不要和我说厕所,我实在不知道face1究竟是男人还是厕所,这样会让我更糊涂,我本来就是自学的,来这里诚心求教。
您现在说的就是我对此类写法感到困惑的关键,
按您的说法,实例是实例,类形式类型,internal static void methodA (IInterf1 face1, IInterf2[][] face2, IInterArray[][] ary), 实例是 face1, face2, 类形式接口类型,而接口类型不能实例化,那这个face1, face2 是什么实例? 是不是某个实现了接口IInterfx的实例? 我只希望得到明确的是或者不是。我已经卡在这类问题上很久了,过不了这关我以前的努力就白费了,谢谢您的耐心帮助
我真有点执迷不悟了,是不是说face1, face2已经实现了接口,是实现了接口的类的一个实例。而且face1 全部实现了接口里的方法?
假设I男人是个接口类型,里面有个方法叫ML(),返回的类型是另外一个接口IBaby
张三和李四两个类都实现了它
那么就可以这样 I男人 man = 张三()或者李四();
而此时在另外一个类里面有个方法:
IBaby MakeBaby(I男人 man, I女人 woman) //I女人也一样是个接口
{
//这里你可以直接调用接口方法,而不用去管具体是张三还是李四,只要man是实现了I男人这个接口的实例就行了
return man.ML();
}类比一下,LZ例子里的face1.GenerateArray(3, lb, ub)方法,其实就是IInterf1这个接口定义的方法,最后那一行也是,只是这个方法返回的是另一个接口 IInterf2[] 的数组类型而已
和平常我们返回的string[]没啥两样,都只是一个Type的形式,所以不能说是生成接口
其实很容易理解。你一直把"实例化"和"实例"拧在一起了。说接口不能实例化是因为接口不能使用普通实例化的语法。例如
public interface IPerson ;
IPerson person = new IPerson();
上面的语法会直接报错,这就叫做"接口不能实例化"但是如果使用某个类继承了接口,例如
public class Man : IPerson
那就可以这样写:
IPerson person = new Man();
person就是IPerson的一个"实例"。
subject to
–x1 + x2 + x3 ≤ 20
x1 – 3x2 + x3 ≤ 30
with these bounds
0 ≤ x1 ≤ 40
0 ≤ x2 ≤ infinity
0 ≤ x3 ≤ infinity
♦
我的问题是:
1)既然都是用实现了接口的类,干吗不直接用类来写API呢,
2)同样:既然方法参数传入的是实现了接口的类, 比如 method1(Iinter1 interf,...)
那必然有class xxx : interf
{
methods in Iinter1()
}
可通篇程序没有任何冠以这个传入的类如何实现这些接口的代码, 实现接口的代码跑哪里去了呢?这是我目前最后一个问题了,从昨天到今天,我还是明白了很多的,谢谢大家:
下面就是例子:PopulateByRow 最好理解, 是逐行写这个这个优化方程:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ILOG.Concert;
using ILOG.CPLEX;namespace CPLEX1
{
public class LPex
{
//Step 7
internal static void Usage()
{
System.Console.WriteLine("usage: LPex1 <option>");
System.Console.WriteLine("Options: -r build model row by row");
System.Console.WriteLine("Options: -c build model colomn by column");
System.Console.WriteLine("Options: -n build model nonzero by nonzero");
}
public static void Main(string[] args)
{
if (args.Length != 1 || args[0].ToCharArray()[0] != '-')
{
Usage();
return;
}
try
{
// Step 3
//step 3
Cplex cplex = new Cplex();
INumVar[][] var = new INumVar[1][];
IRange[][] rng = new IRange[1][]; //step 8
switch (args[0].ToCharArray()[1])
{
case 'r': PopulateByRow(cplex, var, rng);
break;
case 'c': PopulateByColumn(cplex, var, rng);
break;
case 'n': PopulateByNonzero(cplex, var, rng);
break;
default: Usage();
return;
}
// Step 11
cplex.ExportModel("lpex.lp");
//Step 9
if (cplex.Solve())
{
//Step 10
double[] x = cplex.GetValues(var[0]);
double[] dj = cplex.GetReducedCosts(var[0]);
double[] pi = cplex.GetDuals(rng[0]);
double[] slack = cplex.GetSlacks(rng[0]); cplex.Output().WriteLine("Solution status = " + cplex.GetStatus());
cplex.Output().WriteLine("Solution value = " + cplex.ObjValue); int nvars = x.Length; for (int j = 0; j < nvars; ++j)
{
cplex.Output().WriteLine("Variable :" + j + " Value= " + x[j] + " Reduced cost = " + dj[j]);
}
int ncons = slack.Length; for (int i = 0; i < ncons; ++i)
{
cplex.Output().WriteLine("Constraint: " + i + " Slack = " + slack[i] + " pi = " + pi[i]);
}
Console.ReadKey(); }
cplex.End();
}
catch (ILOG.Concert.Exception e)
{
System.Console.WriteLine("Concert exception '" + e + " ' caught");
}
}
// Step 8
//Step 4
internal static void PopulateByRow(IMPModeler model, INumVar[][] var, IRange[][] rng)
{
double[] lb = { 0.0, 0.0, 0.0 };
double[] ub = { 40.0, System.Double.MaxValue, System.Double.MaxValue };
INumVar[] x = model.NumVarArray(3, lb, ub);
var[0] = x;
double[] objvals = { 1.0, 2.0, 3.0 };
model.AddMaximize(model.ScalProd(var[0], objvals)); rng[0] = new IRange[2];
rng[0][0]=model.AddLe(model.Sum(model.Prod(-1.0,x[0]),model.Prod(1.0,x[1]),model.Prod(1.0,x[2])),20.0);
rng[0][1] = model.AddLe(model.Sum(model.Prod(1.0, x[0]), model.Prod(-3.0, x[1]), model.Prod(1.0, x[2])), 30.0);
}
//Step 5
internal static void PopulateByColumn(IMPModeler model, INumVar[][] var, IRange[][] rng)
{
IObjective obj = model.AddMaximize();
rng[0] = new IRange[2];
rng[0][0] = model.AddRange(-System.Double.MaxValue, 20.0);
rng[0][1] = model.AddRange(-System.Double.MaxValue, 30.0); IRange r0 = rng[0][0];
IRange r1 = rng[0][1]; var[0] = new INumVar[3];
var[0][0] = model.NumVar(model.Column(obj, 1.0).And(model.Column(r0, -1.0).And(model.Column(r1, 1.0))), 0.0, 40.0); var[0][1] = model.NumVar(model.Column(obj, 2.0).And(model.Column(r0, 1.0).And(model.Column(r1, -3.0))), 0.0, System.Double.MaxValue);
var[0][2] = model.NumVar(model.Column(obj, 3.0).And(model.Column(r0, 1.0).And(model.Column(r1, 1.0))), 0.0, System.Double.MaxValue); }
// Step 6
internal static void PopulateByNonzero(IMPModeler model, INumVar[][] var, IRange[][] rng)
{
double[] lb = { 0.0, 0.0, 0.0};
double[] ub = { 40.0, System.Double.MaxValue, System.Double.MaxValue};
INumVar[] x = model.NumVarArray(3, lb, ub);
var[0] = x;
double[] objvals = { 1.0, 2.0, 3.0 };
model.Add(model.Maximize(model.ScalProd(x, objvals)));
rng[0] = new IRange[2];
rng[0][0] = model.AddRange(-System.Double.MaxValue, 20.0);
rng[0][1] = model.AddRange(-System.Double.MaxValue, 30.0);
rng[0][0].Expr = model.Sum(model.Prod(-1.0, x[0]), model.Prod(1.0, x[1]), model.Prod(1.0, x[2])); rng[0][1].Expr=model.Sum(model.Prod(1.0,x[0]),model.Prod(-3.0,x[1]), model.Prod(1.0, x[2])); x[0].Name="x1";
x[1].Name = "x2";
x[2].Name = "x3"; rng[0][0].Name = "c1";
rng[0][1].Name="c2";
} }
}
再次感谢大家的回复
{
double[] lb={1,2,3};
double[] ub={4,5,6};
IInterf2[] x= face1.GenerateArray(3, lb, ub):
ary[0] = new IInterArray[2]
ary[0][1]=face1.AddLe( something inside )
}
这里传进来的face1就表示是实现了接口IInterf1的的类。所以face1的方法就是实现类实现的方法。假如借口是模型,则实现类就是用模型做出来的实在的东西了。
的接口解析真的很有道理
谢谢回复, 可是我看CPLEX API,每一个接口都有很多成员和方法 比如INumVar和IMPMOdeler, 可没有一句是讲如何实现这些方法的呀。我看他们的API,好多都是只写了overloaded, 这是为什么?IBM CPLex的.net 和Java的API在这个链接:http://publib.boulder.ibm.com/infocenter/cosinfoc/v12r2/index.jsp?topic=/ilog.odms.cplex.help/html/refcallablelibrary/html/overview.html.能帮我彻底搞清楚实在是感激不尽
晕。既然是官方的API,那当然是只有接口方法签名,怎么可能公布具体的实现代码?给出一份接口文档来,满足你的调用就可以了。这有什么可糊涂的……
抱歉我才学了两星期,一般接口在教材上写的都是只有方法名称没有方法体,当某个类实现了接口要自己写实现接口里方法的代码。 你的意思是说 官方的接口实际上都有实现接口内方法的代码, 而我们只要写签名就能在实现这个接口的类中实现接口的方法。比如interface ISpeeding
{
void SpeedAt();}
而实现这个接口的类是需要打印出超速的速度值来。 如果这个接口像IBM Cplex中的那样是个官方接口,那某个类实现了这接口,打印输出语句就自动生成了? 不明白。难道只要我们签名 写上速度值就能调用输出方法speedAt(speedValue)?
比如先有一个方法
bool Greater(object obj1,object obj2);
如果obj1大于obj2则返回true。
但担心使用这个方法的人传入的参数压根就不能比较,所以制定个接口
interface IComparable{
int CompareTo(object obj);
}
上面的方法就变为
bool Greater(IComparable obj1,IComparable obj2);
这里参数类型IComparable的意思是,任何实现了IComparable这个接口的类型。不是所有的object都能行了,要用这个方法先要给自己的类型实现IComparable。IComparable里有CompareTo方法。Greater就变成
bool Greater(IComparable obj1,IComparable obj2){
if(obj1.CompareTo(obj2)>0) return true;
return false;
然后会发个说明:
意思是说,如果你想使用Greater方法,并且返回你想要的结果,得按照这个来。不按这个在自己的类型里实现CompareTo方法,使用Greater虽然不给报错,但也不会是正确的结果。怎么实现自己看着办。自己的类型:
class MyClass{
string ID;
public MyClass(string id){ID=id;}
}
这个类型目前显然和IComparable一点关系没有,不能传给Greater,要先实现接口
class MyClass:IComparable{
string ID;
public MyClass(string id){ID=id;}
public void Abc(){do something;}
public int CompareTo(object obj){return 1;}
}
然后
MyClass c1=new MyClass("lambertapple1");
MyClass c2=new MyClass("lambertapple2")
Greater(c1,c2);
就能运行了,虽然可能不会是想要的结果。如果要获得想要结果,CompareTo具体实现就要参考说明写。
Greater方法不是只给MyClass用的,很可能有Greater的时候MyClass根本就不存在。如果之后又有了MyClass2,只要给MyClass2也实现了IComparable,就也能当Greater的参数。由于在使用的时候只关心CompareTo方法,不关心Abc里do了什么,所以也可以这么写
IComparable c1=new MyClass("lambertapple1");
IComparable c2=new MyClass("lambertapple2")
Greater(c1,c2);
这时候c1和c2只能用CompareTo方法,Abc用不了,要用Abc得先转类型
class MyClass{
string ID;
public MyClass(string id){ID=id;}
}
应为自己的类型:
class MyClass{
string ID;
public void Abc(){do something;}
public MyClass(string id){ID=id;}
}
定义运行的接口
inferface IRun
{
void Run();
}class dog:IRun
{
void Run()
{
Console.WriteLine("狗在跑");
}
}class cat:IRun
{
void Run()
{
Console.WriteLine("猫在跑");
}
} class Program
{
static void Main(string[] args)
{
//我只关系要什么去跑,
IRun dog=new dog();
Run(dog);
IRun cat=new cat();
Run(cat);
} static void Run(IRun object)
{
//我只管跑
object.Run();
}
}
您这个例子里至少在继承接口的类中自己定义了run()方法, 然后调用接口生成新的实现了接口的对象。可是IBM CPLEX里根本就没有对继承了接口的类的方法的实现代码,而直接就用接口生成实现了接口的类的对象, 究竟怎么实现的完全没有交代。
你要关注的是在调用LPex.methodA(...)是否传递的对象实现了IInterf1接口我那个例子中的
static void Run(IRun object)
{
//我只管跑
object.Run();
}
就相当于你的methodA